0
votes

I am trying to run an cpp client application to connect to a server when Raspberry Pi is booted and connected to the Internet. I validated this CPP executable (Asio_Client_Main) works fine when manually run in the terminal. (pi@raspberrypi:~/Desktop $ ./Asio_Client_Main - Once connected, it sends a message to a server.)

First time to use Systemd, and this is what I did.

  1. made client_test_a.service and copied it to /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

It's loaded but inactive. I think it's just exited, but how can I keep it connected? I also don't think it's connected to the server because I don't see any client connection on the server-side. Any advice would be appreciated. Thanks!

I tried Type=oneshot. Using RPi 4 B with wifi connection.

Main Cpp Code

#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;
}

UPDATE 2/9/2021:

Prints before and after While Loop Please see the Main.cpp Above to see the complete code

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; 

I also used a bash script instead of executing the program directly.

mystartup.sh

#!/bin/bash
# Store first parameter in a variable, which should be the log file location.
LOG_FILE="$1"
# 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

Then

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 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.

So when I ran the program, it does not exit the loop. But when using systemd, it just exits the loop without taking user inputs. How can I keep it running in the foreground taking user inputs?

1
I’m voting to close this question because your question is not "Programming" related it is better asked on the StackExchange site Raspberry pi StackExchange. That said, it appears your systemd service did execute the file and it did run, but apparently your file isn't a daemon that remains resident after being started. If that is the case you would look at the oneshot feature for starting the file.David C. Rankin
Where's the code for the service? I bet ultimately that's what's not working.Andy
@Andy The program is on the desktop. WorkingDirectory=/home/pi/Desktop. The service file is in /etc/systemd/system/ Does it matter where I put the executable here?mqmarathon
no, the actual code, there is probably a problem with the actual code.Andy
@Andy I added the main C++ code to the post. It compiles and executes properly when I run it in a command line.mqmarathon

1 Answers

0
votes

Systemd is not designed for programs with console interaction. It's designed for background services or tasks to run on system events.

As such unless you use redirection in your bash script std::cin will not be connected to anything (let alone a terminal - which terminal should it use anyways?).

If you're going to run a chat server as a background service, make the part without user interaction the service executable. For example, the service need only accept input via network connections and optionally write additional output to a file (such as logging) .

If the program should read some thing like configuration from standard input, use input redirection to read it from a file instead.