How to pipe Systemd service standard output from ExecStart to shell, ex. bash? - linux

I have a Systemd service that starts the process of output which I need to execute as a normal Bash script
[Unit]
Description=Example app
[Service]
Type=simple
PIDFile=/var/run/app.pid
Sockets=app.socket
StandardInput=fd:app.socket
#StandardOutput=fd:sh
StandardError=journal
ExecStart=/usr/bin/app -a | sh #
[Install]
WantedBy=default.target
Instead of execution, the output of the application falls into the log.
Tell me how can I solve this problem?

you can't really pipe stuff in ExecStart, but you can do:
ExecStart=/bin/bash -c '/usr/bin/app -a | sh '

Related

Interactive script on stop systemd service

I need to run script when system shutting down (reboot...) that asks user for contributing some actions:
#!/bin/bash
tty
echo ARE YOU SURE?:
read test
echo $test
[Unit]
Description= Minetest server
[Service]
StandardInput=tty-force
ExecStart= /bin/true
ExecStop=/home/user/test.sh
Type=oneshot
StandardInput=tty
StandardOutput=tty
TTYPath=/dev/tty8
TTYReset=yes
TTYVHangup=yes
RemainAfterExit=true
If I'm executing it as ExecStop, I have output like:
not a tty
INPUT TEST:
and no ask for input
Whats wrong with it?
the ExecStop is called by another script ,not from your console, so there is no tty device attached
and the built-in command read requires input to be a tty device
btw , asking user to contribute via a script is fragile and uncontrollable

Running bash script as a service and write to another bash script is not working

I have the following problem using bash script.
Here is what I have inside the 'startup' script file:
#!/bin/bash
java -cp ../lib/online-store.jar:../lib/* com.online.store.Main
OnlineStorePID=$!
if [$OnlineStorePID -ne 0] then
echo "kill $OnlineStorePID" > shutdown
fi
Basically what I do, is to run a java application, get the process id and write it to another bash file. All this process works when I execute the startup script, and the 'shutdown' script file is updated successfully with a line containing 'kill processIDNumber' cmd.
Now I have tried to create a service on Ubuntu for this script using the following commands:
sudo systemctl daemon-reload
sudo systemctl enable online-store.service
sudo systemctl start online-store
When I start the service the java application starts successfully, but the shutdown script file is not updated. It seems that the 'echo "kill $OnlineStorePID" > shutdown' line is not executed. I don't get any complain errors. Does anyone knows what's the problem here.
Here is my service file:
[Unit]
Description=Online store service
Requires=multi-user.target
After=multi-user.target
Wants=mysql.service
[Service]
WorkingDirectory=/home/user/Desktop/online-store-service
#path to executable.
ExecStart=/home/user/Desktop/online-store-service/bin/startup
ExecStop=/home/user/Desktop/online-store-service/bin/shutdown
SuccessExitStatus=143
TimeoutStopSec=10
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Change your script and run the java command like below as back ground process
java -cp ../lib/online-store.jar:../lib/* com.online.store.Main >/dev/null 2>&1 &

systemd env vars from an executable script

I have the following systemd service file:
[Unit]
Description=My description
[Service]
Type=simple
User=myuser
ExecStart=/path/to/my/start_script.sh
ExecStop=/path/to/my/stop_script.sh
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=30s
[Install]
WantedBy=multi-user.target
My start_script.sh is used to start a java application BUT I need to get some variables from an executable ksh script custom_script.sh.
I tried the following systemd params with no success:
ExecStartPre
EnvironmentFile
Is there a way to make it work?
Thank you in advance heroes.
In order to have the variables from custom_script.sh accessible from your Java process, you'll have to insert them into the environment somehow, in a way that systemd will be pleased with. The docs for the EnvironmentFile= directive say that any line that is not a parameter assignment statement with an = sign will be ignored. So we need to take your script and cook it down so that all we have left are the variables after running it.
What you can do is create an auxiliary "distillery" service that sources your custom_script.sh file and prints every value in the environment to another file called custom_script.env. Then you can provide the "distilled" environment file to the Java process in the EnvironmentFile directive.
So if your original service adds After= and Requires= like this,
[Unit]
Description=My description
After=custom-script-distillery
Requires=custom-script-distillery
[Service]
Type=simple
User=myuser
EnvironmentFile=/path/to/my/custom_script.env
ExecStart=/path/to/my/start_script.sh
ExecStop=/path/to/my/stop_script.sh
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=30s
[Install]
WantedBy=multi-user.target
Then the distillery could look like this:
[Unit]
Description=My service to distill custom_script.sh to an EnvironmentFile
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c 'set -o allexport; source /path/to/my/custom_script.sh; set +o allexport; unset IFS; set | grep -v "^BASH" > /path/to/my/custom_script.env'

Register daemon controllable by start and stop command in Linux

Many system daemon can be started using start/stop command. I was just curious how start/stop works on Linux system. Say I wrote a daemon executable, how should I configure it so that it can be controlled by start/stop in Linux.
I make a daemon in linux (ArchLinux) few years ago, and it works every day perfectly.
There are 2 ways to do this. Short way and long way:
Short Way:
Create a file in /etc/systemd/system/ called for example mydaemon.service :
/etc/systemd/system/mydaemon.service
[Unit]
Description=This is my first daemon! - Fernando Pucci
After=network.target
[Service]
User=root
WorkingDirectory=/root
Type=oneshotmc
RemainAfterExit=yes
ExecStart=/bin/echo -e "Daemon started"
ExecStop=/bin/echo -e "Daemon Stopped"
[Install]
WantedBy=multi-user.target
This service does nothing but show Daemon Started or Stopped. You can change echoes by the sentences you need.
If you need to run some script, try the Long way:
Long way
Create a file in some directory, like root folder or /usr/lib/systemd/scripts called for example
/root/mydaemon.sh
start() {
<your start sentences here
and here>
}
stop() {
<your stop sentences here
and here>
}
case $1 in
start|stop) "$1" ;;
esac
You must to make it runnable (chmod x)
(And you can execute it with start or stop parameter to test it.)
And as second step, create another file in
/usr/lib/systemd/system/mydaemon.service
[Unit]
Description=Second daemon of Fernando Pucci
After=network.target
[Service]
User=root
WorkingDirectory=/root
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c '/root/mydaemon.sh start'
ExecStart=/bin/echo -e "MyDaemon Started"
ExecStop=/bin/bash -c '/root/mydaemon.sh stop'
ExecStop=/bin/echo -e "MyDaemon Stopped"
[Install]
WantedBy=multi-user.target
Starting and Stopping
systemctl start mydaemon
systemctl stop mydaemon
systemctl status mydaemon
systemctl enable mydaemon
systemctl disable mydaemon
You (and someone) can send me a private msg for help about that.

How to run last and print my script output during boot with systemd?

I’m trying to configure my host during deployment process and to give an output to the screen of what my configuration script is doing.
In RHEL6 it was easy i was echoing what I want to screen or used dialog to display the output, and only when my script was done i got the login prompt.
( I used rc3.d or rc5.d folder with script name S99.myscript.sh)
In RHEL7 i can’t mimic this process.
rc.local does not display my output during booting and also its not guaranteed it will run last.
I guess I need to create a systemd service file that will run my script.
But how do I output the result to the screen while booting?
And how do I make sure I will not get the log-in prompt before my script ends?
below service example works like a charm :)
[Unit]
Description=ldt_bootscript1.service
After=network.target
Before=getty#tty1.service
[Service]
Type=oneshot
ExecStart=/bin/bash -c "/bin/bash /tmp/ldt_scripts/postinstall/rc.firstboot.qas | /usr/bin/dialog --clear --backtitle \"Linux Deployment\" --title \"tests\" --progressbox 20 70 > /dev/console 2>&1"
ExecStartPre=/usr/bin/echo -e \033%G
ExecReload=/bin/kill -HUP $MAINPID
RemainAfterExit=no
WorkingDirectory=/
Environment=TERM=xterm
[Install]
WantedBy=multi-user.target

Resources