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,这就是我做的。
- 制作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
sudo systemctl start 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 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.
- 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 将不会连接到任何东西(更不用说终端了——它应该使用哪个终端?)。
如果您要运行 将聊天服务器作为后台服务,请将无需用户交互的部分设为服务可执行文件。例如,该服务只需要通过网络连接接受输入,并可选择将其他输出写入文件(例如日志记录)。
如果程序应该从标准输入读取配置之类的东西,请改用输入重定向从文件中读取它。
我正在尝试 运行 cpp 客户端应用程序在 Raspberry Pi 启动并连接到 Internet 时连接到服务器。我验证了这个 CPP 可执行文件 (Asio_Client_Main) 在终端中手动 运行 时工作正常。 (pi@raspberrypi:~/Desktop $ ./Asio_Client_Main - 连接后,它会向服务器发送消息。)
第一次使用Systemd,这就是我做的。
- 制作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
sudo systemctl start 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 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.
- 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 将不会连接到任何东西(更不用说终端了——它应该使用哪个终端?)。
如果您要运行 将聊天服务器作为后台服务,请将无需用户交互的部分设为服务可执行文件。例如,该服务只需要通过网络连接接受输入,并可选择将其他输出写入文件(例如日志记录)。
如果程序应该从标准输入读取配置之类的东西,请改用输入重定向从文件中读取它。