Raspberry Pi 使用 Systemd 自动启动可执行文件,已加载但不活动(已死)

Raspberry Pi Auto-start Executable with Systemd, Loaded but Inactive (Dead)

我正在尝试 运行 cpp 客户端应用程序在 Raspberry Pi 启动并连接到 Internet 时连接到服务器。我验证了这个 CPP 可执行文件 (Asio_Client_Main) 在终端中手动 运行 时工作正常。 (pi@raspberrypi:~/Desktop $ ./Asio_Client_Main - 连接后,它会向服务器发送消息。)

第一次使用Systemd,这就是我做的。

  1. 制作client_test_a.service并复制到/etc/systemd/system/
[Unit]
Description=Client Test A
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
WorkingDirectory=/home/pi/Desktop
ExecStart=/home/pi/Desktop/Asio_Client_Main

StandardOutput=console

[Install]
WantedBy=multi-user.target
  1. sudo systemctl start client_test_a.service

  2. sudo systemctl status client_test_a.service

● client_test_a.service - Client Test A
   Loaded: loaded (/etc/systemd/system/client_test_a.service; enabled; vendor pr
   Active: inactive (dead) since Sun 2021-02-07 18:00:02 EST; 10min ago
  Process: 1586 ExecStart=/home/pi/Desktop/Asio_Client_Main (code=exited, status
 Main PID: 1586 (code=exited, status=0/SUCCESS)

Feb 07 18:00:02 raspberrypi systemd[1]: Started Client Test A.
Feb 07 18:00:02 raspberrypi systemd[1]: client_test_a.service: Succeeded.
  1. sudo systemctl enable client_test_a.service

已加载但未激活。我认为它刚刚退出,但我怎样才能保持连接? 我也不认为它已连接到服务器,因为我在服务器端看不到任何客户端连接。任何意见,将不胜感激。谢谢!

我尝试了 Type=oneshot。使用 RPi 4 B 和 wifi 连接。

主要 Cpp 代码

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include "Asio_Client.h"

int main(int argc, char* argv[])
{
    std::vector<std::vector<int>> lunarPixel;
    
    std::ifstream file("LunarPixel.txt");
    std::string str;

    while (std::getline(file, str))
    {
        // Process str
        std::vector<int> result;
        std::istringstream iss(str);

        for (std::string str; iss >> str;)
        {
            result.push_back(std::stoi(str));
        }

        lunarPixel.push_back(result);
    }

    auto& lunar_time = lunar_timer::Init();
    lunar_time.set_lunar_pixel(lunarPixel);

    
    //--------------------------------------------------------------------------------------------------------------
    
    
    try
    {
        std::vector<std::vector<int>> lunarPixel;

        std::ifstream file("LunarPixel.txt");
        std::string str;

        while (std::getline(file, str))
        {
            // Process str
            std::vector<int> result;
            std::istringstream iss(str);

            for (std::string str; iss >> str;)
            {
                result.push_back(std::stoi(str));
            }

            lunarPixel.push_back(result);
        }

        auto& lunar_time = lunar_timer::Init();
        lunar_time.set_lunar_pixel(lunarPixel);

        boost::asio::io_context io_context;
        tcp::resolver resolver(io_context);

        const std::string ipAddress = "192.***.*.*"; //ip
        const std::string portNum = "2120";

        auto endpoints = resolver.resolve(ipAddress, portNum);
        chat_client c(io_context, endpoints, lunar_time);

        std::thread t([&io_context]() { io_context.run(); });

        char line[chat_message::max_body_length + 1];
        
        std::cout << "Before_ while (std::cin.getline(line, chat_message::max_body_length + 1))" << std::endl; 

        while (std::cin.getline(line, chat_message::max_body_length + 1))
        {
            chat_message msg;
            msg.body_length(std::strlen(line));
            std::memcpy(msg.body(), line, msg.body_length());
            msg.encode_header();
            c.write(msg);
        }
            
        std::cout << "Exited" << std::endl;     

        c.close();
        t.join();
    }
    catch (std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
    }

    return 0;
}

2021 年 2 月 9 日更新:

While 循环前后打印 完整代码请看上面的Main.cpp

std::cout << "Before_ while (std::cin.getline(line, chat_message::max_body_length + 1))" << std::endl; 

while (std::cin.getline(line, chat_message::max_body_length + 1))
{
    chat_message msg;
    msg.body_length(std::strlen(line));
    std::memcpy(msg.body(), line, msg.body_length());
    msg.encode_header();
    c.write(msg);
}

std::cout << "Exited" << std::endl; 

我还使用了一个bash脚本,而不是直接执行程序。

mystartup.sh

#!/bin/bash
# Store first parameter in a variable, which should be the log file location.
LOG_FILE=""
# Set a default log file location if the parameter was empty, i.e. not specified.
if [ -z "$LOG_FILE" ]
then
  LOG_FILE="/var/log/testlog.txt"
fi

cd /home/pi/Desktop
./Asio_Client_Main

然后

sudo systemctl 启动 client_test_a.service sudo systemctl status client_test_a.service

● client_test_a.service - Client Test A
   Loaded: loaded (/etc/systemd/system/client_test_a.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Tue 2021-02-09 23:09:58 EST; 3s ago
  Process: 2004 ExecStart=/bin/bash /usr/local/bin/mystartup.sh (code=exited, status=0/SUCCESS)
 Main PID: 2004 (code=exited, status=0/SUCCESS)

Feb 09 23:09:58 raspberrypi bash[2004]: Before_ while (std::cin.getline(line, chat_message::max_body_length + 1))
Feb 09 23:09:58 raspberrypi bash[2004]: Exited
Feb 09 23:09:58 raspberrypi systemd[1]: client_test_a.service: Succeeded.
Feb 09 23:09:58 raspberrypi systemd[1]: Started Client Test A.

所以当我运行程序时,它并没有退出循环。但是当使用 systemd 时,它只是退出循环而不接受用户输入。我怎样才能将它 运行ning 保持在前台接受用户输入?

Systemd 不是为具有控制台交互的程序设计的。它专为 运行 系统事件的后台服务或任务而设计。

因此,除非您在 bash 脚本中使用重定向,否则 std::cin 将不会连接到任何东西(更不用说终端了——它应该使用哪个终端?)。

如果您要运行 将聊天服务器作为后台服务,请将无需用户交互的部分设为服务可执行文件。例如,该服务只需要通过网络连接接受输入,并可选择将其他输出写入文件(例如日志记录)。

如果程序应该从标准输入读取配置之类的东西,请改用输入重定向从文件中读取它。