Problem :
I am trying to run a systemd service for my binary. The binary expects an argument for –public-ip field, which i supply through curl https://ipinfo.io/ip
. I did in the following way but the executable is not getting started correctly.
When I checked with sudo journalctl -f
, i saw that the binary cant see the argument supplied to –public-ip option, so it is hanging in a loop continuously trying. WHen I call the exact same command from the terminal it seems to work.
What am i missing here ?
I am on 20.04 Ubuntu server
[Unit]
Description=test node
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=$(whoami)
ExecStart='/my/working/directory/binary --public-ip "$(curl https://ipinfo.io/ip)"'
[Install]
WantedBy=multi-user.target
Solution :
systemd does its own minimalistic shell-style command line parsing of the contents of ExecStart=
and other parameters. Command substitution ($()
) is not supported. You
need an actual shell to handle $(curl https://ipinfo.io/ip)
.
ExecStart=/bin/sh -c 'exec /my/working/directory/binary --public-ip "$(curl https://ipinfo.io/ip)"'
Notes:
- The shell may be able to locate
curl
via the default$PATH
; if not, then use/full/path/to/curl
or expand$PATH
. - After the shell handles
$()
, it will replace itself with yourbinary
thanks toexec
. This way you can still useType=simple
(notType=forking
). - You may find
SyslogIdentifier=foo
useful (see this answer).