ExecStart bash script fails; However, running it manually works - python

I need help with bash and systemctl service...
My problem is that my company requires me to automate the boot of all virtual machines running on our KVM server (CentOS), we have 5 physical hosts in total; however, I came across an issue on one of them, which I recently updated my VM versions, where my service <vmx.service> located under /etc/systemd/system does not run my ExecStart=/bin/bash -c './vmx.sh -lv --start --cfg config/pod8/vmx1.conf' bash script.
file: vmx.service
[Unit]
Description=Juniper vMX Router
Wants=network-online.target
After=network-online.target
After=libvirtd.service
[Service]
WorkingDirectory=/home/vMX-21.1R1/
Environment="PATH=/opt/rh/python27/root/usr/bin:/usr/lib64/qt3.3/bin:/usr/local/sbin:/usr/local/bin:/$
Type=oneshot
User=root
Group=root
RemainAfterExit=true
## Commands used to stop/start/restart the vMX
ExecStart=/bin/bash -c './path-python.sh'
ExecStart=/bin/bash -c './vmx.sh -lv --start --cfg config/pod8/vmx1.conf' <<<<<<<<<<<<<<<<<<<<<<<
ExecStart=/bin/bash -c './vmx.sh -lv --start --cfg config/pod8/vmx2.conf'
ExecStart=/bin/bash -c './vmx.sh -lv --start --cfg config/pod8/vr-device.conf'
[Install]
WantedBy=multi-user.target
Here is my service status:
Loaded: loaded (/etc/systemd/system/vmx.service; enabled; vendor preset: disabled)
Active: failed (Result: exit-code) since Mon 2021-11-29 14:04:37 AEST; 2h 4min ago
Process: 2324 ExecStart=/bin/bash -c ./vmx.sh -lv --start --cfg config/pod8/vmx1.conf (code=exited, status=2)
Process: 1877 ExecStart=/bin/bash -c ./path-python.sh (code=exited, status=0/SUCCESS)
Main PID: 2324 (code=exited, status=2)
Nov 29 14:04:37 Juniper-KVM3 bash[2324]: import netifaces as ni
Nov 29 14:04:37 Juniper-KVM3 bash[2324]: ImportError: No module named netifaces
Nov 29 14:04:37 Juniper-KVM3 bash[2324]: Log file........................................../home....log
Nov 29 14:04:37 Juniper-KVM3 bash[2324]: ==================================================
Nov 29 14:04:37 Juniper-KVM3 bash[2324]: Aborted!. 1 error(s) and 0 warning(s)
Nov 29 14:04:37 Juniper-KVM3 bash[2324]: ==================================================
Nov 29 14:04:37 Juniper-KVM3 systemd[1]: vmx.service: main process exited, code=exited, status=2...MENT
Nov 29 14:04:37 Juniper-KVM3 systemd[1]: Failed to start Juniper vMX Router.
Nov 29 14:04:37 Juniper-KVM3 systemd[1]: Unit vmx.service entered failed state.
Nov 29 14:04:37 Juniper-KVM3 systemd[1]: vmx.service failed.
I thought that the error: ImportError: No module named netifaces would be fixed by running
pip uninstall netifaces && pip install netifaces as read in this article.
However, it did not work either, Regardless, the weirdest thing is that when I run the same script in my terminal, it works:
[root#system]# ./vmx.sh -lv --stop --cfg config/pod8/vmx1.conf
[...]
==================================================
VMX Status Verification Completed.
==================================================
Log file........................................../home/vMX-21.1R1/build/8m1/logs/vmx_1638166233.log
==================================================
Thank you for using VMX
==================================================
I made sure that SElinux is disabled:
SELinux status: disabled
It is worth noting that ./path-python.sh script runs without a problem, this script allows me to change my python27 path, otherwise my VM Installation would fail, but I can certainly say that this problem has nothing to do with python itself, as the script works only when I run it within my terminal. (My Other servers works as expected using the same scripts and bash, I have no clue what is wrong).

The ExecStart commands are run separately, not in the same shell or somesuch.
In other words, if
ExecStart=/bin/bash -c './path-python.sh'
sets up some Python-related path tweaks, they will not be available for the subsequent ExecStart commands.
Instead of a script that "changes your python27 path" I would recommend you to set up a virtualenv for that Python environment with the packages you require installed in it, so you could just use that virtualenv's interpreter in your vmx.sh. If you can't edit vmx.sh, you could set up a script that does something like
#!/bin/bash
source /opt/myvirtualenv/bin/activate
./vmx.sh -lv --start --cfg config/pod8/vmx1.conf
# ...
and run that instead; the activate script ensures that virtualenv's Python is the primary one for that shell session.

So, after playing around with virtualenv I finally made it work! Previously, when running ./vmx.sh script, it would require the system to use Python2.7; however, every time my host would reboot, if I wanted to fully automate the boot of all of my VMs, I would require to change the PATH of Python by running manually the following command onto my terminal:
echo 'export PATH=/opt/rh/python27/root/usr/bin:$PATH' >> /etc/profile
PATH=/opt/rh/python27/root/usr/bin:$PATH
export PATH
cd /opt/rh/python27/ && . enable && pip install netifaces pyyaml
Instead of running the previous commands from a .sh script, which ended up not working for me, It was pointed out that "Python-related path tweaks, will not be available for the subsequent ExecStart commands". For that reason, I did the following:
Instead of running scl enable python27 bash (which would make as default my Python Version until you logout), I decided to keep the changes by creating a script under /etc/profile.d/
#!/bin/bash
source scl_source enable python27
I installed virtualenv pip install virtualenv
Created a virtual environment virtualenv --python=/usr/bin/python2.7 vMX-ENV which I would use to install all my packages and scripts to install my VMs
Activated my Virtual Environment source /home/vMX-ENV/bin/activate
Created a Directory (vMX-*) where ./vmx.sh script will be located.
# ls
bin lib lib64 pyvenv.cfg vMX-21.1R1
Inside of that Directory, I created a bash script that will be initiated by the service when on boot, I called it: pyrun.sh, this script runs the ./vmx.sh script "Credit: AKX"
#!/bin/bash
source /home/vMX-ENV/bin/activate
./vmx.sh -lv --start --cfg config/pod17/vmx1.conf
# ...
Created the vmxd.service and ExecStart=/bin/bash -c './pyrun.sh'
By creating a virtualenv I was able to isolate my Python project by only creating a unique environment with all the needed packages and running only Python2.7 which is required to run ./vmx.sh
After rebooting the host, here is the journalctl -u vmxd.service successful output as a result:
Starting Juniper vMX Router...
==================================================
Welcome to VMX
==================================================
[...]

Related

Python script does not restart properly with systemd

I am learning how to restart a Python script in case of error (following this tutorial, however with some small tweaks regarding filenames and alike). First things first, the needed files:
/home/myuser/Desktop/test/test.py:
from datetime import datetime
from time import sleep
path = "/home/dec13666/Desktop/test/log.txt"
while True:
with open(path, "a") as f:
now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
f.write(now+"\n")
f.close()
sleep(1)
raise Exception("Error Simulation!!!")
davidcustom.service:
[Unit]
Description=Python Script Made By Me
After=multi-user.target
[Service]
RestartSec=10
Restart=always
ExecStart=python3 /home/myuser/Desktop/test/test.py
[Install]
WantedBy=multi-user.target
Finally, the commands run:
sudo nano /etc/systemd/system/davidcustom.service
sudo systemctl daemon-reload
sudo systemctl enable davidcustom.service
sudo systemctl start davidcustom.service
sudo systemctl status davidcustom.service
The message I am getting:
● davidcustom.service - Python Script Made By Me
Loaded: loaded (/etc/systemd/system/davidcustom.service; enabled; vendor preset: enabled)
Active: activating (auto-restart) (Result: exit-code) since Sun 2022-09-04 14:12:12 EDT; 8s ago
Process: 3341 ExecStart=python3 /home/myuser/Desktop/test/test.py (code=exited, status=1/FAILURE)
Main PID: 3341 (code=exited, status=1/FAILURE)
CPU: 100ms
Notes:
When I run test.py manually, it works OK, but then that python script is run from a service (as seen here), it generates that error.
I have tried to set User=myusername and Type=simple, in davidcustom.service ([Service]), with no difference in the results.
What am I doing wrong?
ExecStart requires an absolute path to the executable, it doesn't search $PATH. So use
ExecStart=/usr/bin/python3 /home/myuser/Desktop/test/test.py
(assuming that's where python3 is installed -- you can use type python3 to get the actual location).
I inadvertently added some wrong indentation in the original code (corrected by now in the original post). That solved my issue; when running sudo systemctl status davidcustom.service, now the service is active:
● davidcustom.service - Python Script Made By Dave
Loaded: loaded (/etc/systemd/system/davidcustom.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2022-09-04 16:16:02 EDT; 23ms ago
Main PID: 4287 (python3)
Tasks: 1 (limit: 14215)
Memory: 3.0M
CPU: 16ms
CGroup: /system.slice/davidcustom.service
└─4287 python3 /home/dec13666/Desktop/test/test.py
Other suggestions which would worth keeping in mind, but were NOT necessary for my case (thanks #Barmar & #tdelaney):
Use an absolute path at ExecStart (easily obtainable by running which python command)
If you only want to use your User and/or Group, then explicitely write those parameters.
The 2 previous suggestions should be added in [Service], in your service script:
[Service]
RestartSec=10
Restart=always
ExecStart=/usr/bin/python3 /home/myuser/Desktop/test/test.py
User=youruser
Group=yourgroup
Read the comments in the original post, for other options.
Thanks.

How to get crontab job depencies working and avoid command not found

My cron job needs to run a shell script which calls python commands which depends on python and a pip package. How can I get my script to work in cron?
My shell script is simply
#!/bin/bash
TOKEN=XXXX-XXXX-XXXX
bdate=$(date -d "$date -30 days" +"%Y%m%d")
# slack-cleaner was installed with pip install slack-cleaner
slack-cleaner --token $TOKEN --message --channel ci-builds --botname circle-ci --before $bdate
My crontab is
50 3 * * * bash /home/myuser/bin/slack_cleaner.sh
I get the errors in the mail log
tail -f /var/mail/myuser # outputs
X-Cron-Env: <HOME=/home/myuser>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=myuser>
Message-Id: <20210108034301.5F00F44531#someplace>
Date: Fri, 8 Jan 2021 03:43:01 +0000 (UTC)
/home/myuser/bin/slack_cleaner.sh: line 5: slack-cleaner: command not found
Load the user's PATH variable in crontab -e
copy the output of echo $PATH and then run crontab -e
add these 2 lines before your cron job(s)
SHELL=/bin/bash
PATH=<paste what you copied in step 2 here>

Start a python script at startup automatically?

I followed multiple tutorials available on stackoverflow about starting a python script at startup but none of them works.
I need to activate a virtualenv then start a flask server
I tried
init.d method
I made an start.sh in /etc/init.d/
#!/bin/sh
### BEGIN INIT INFO
# Provides: skeleton
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Should-Start: $portmap
# Should-Stop: $portmap
# X-Start-Before: nis
# X-Stop-After: nis
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# X-Interactive: true
# Short-Description: Example initscript
# Description: This file should be used to construct scripts to be
# placed in /etc/init.d.
### END INIT INFO
cd /home/ion/
source /home/ion/py35/bin/activate
cd /home/ion/Desktop/flask/
nohup python main.py &
echo "Done"
Its permissions are chmod at +x
ion#aurora:/etc/init.d$ ll start.sh
-rwxr-xr-x 1 root root 625 Jun 25 19:10 start.sh*
Went to /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
/etc/init.d/start.sh
exit 0
Didn't work
cronjob method
sudo crontab -e
and appended
#reboot sh '/etc/init.d/start.sh'
Didn't worked either , where am I wrong?
Manual triggered logs
(py35) ion#aurora:~/Desktop/flask$ python main.py
WARNING:tensorflow:From /home/ion/Desktop/flask/encoder.py:57: calling l2_normalize (from tensorflow.python.ops.nn_impl) with dim is deprecated and will be removed in a future version.
Instructions for updating:
dim is deprecated, use axis instead
2018-06-25 19:34:05.511943: I tensorflow/core/platform/cpu_feature_guard.cc:140] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
* Serving Flask app "main" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://localhost:5505/ (Press CTRL+C to quit)
* Restarting with stat
1) Don't use old "init.d" method. Use something modern. If you have Ubuntu 15.04 and higher, you can use Systemd to create daemon that will be started automatically at startup. If you have for example Ubuntu older than 15.04 - use Upstart.
For Systemd:
Create unit file in /lib/systemd/system/you_service_name.service with the following content (as far as I can see your python script doesn't spawn new process while running, so Type should be simple. More info here):
[Unit]
Description=<your_service_name>
After=network.target network-online.target
[Service]
Type=simple
User=<required_user_name>
Group=<required_group_name>
Restart=always
ExecStartPre=/bin/mkdir -p /var/run/<your_service_name>
PIDFile=/var/run/<your_service_name>/service.pid
ExecStart=/path/to/python_executable /path/to/your/script.py
[Install]
WantedBy=multi-user.target
Save this file and reload systemd:
sudo systemctl daemon-reload
Then add your service to autostart:
sudo systemctl enable you_service_name.service
you should see that Systemd created required symlinks after enable action.
Reboot and see if it's up and running (ps aux | grep python or sudo systemctl status you_service_name.service). If there is something weird - check Systemd journal:
sudo journalctl -xe
UPD:
To launch your python script in desired virtualenv, just use this expression in your service unit file:
ExecStart=/venv_home/path/to/python /venv_home/path/to/your/script.py
2) You can also use crontab, but you need to specify full path for desired shell there, for example:
#reboot /bin/bash /path/to/script.sh
If you need additional help - just let me know here.

Failed to start firewalld on centos 7

I installed firewalld on my centos server but as I tried to start it I got this:
$ sudo systemctl start firewalld
Job for firewalld.service failed. See 'systemctl status firewalld.service' and 'journalctl -xn' for details.
here is the systemctl status:
sudo systemctl status firewalld
firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled)
Active: failed (Result: exit-code) since پنجشنبه 2016-04-07 05:36:17 UTC; 9s ago
Process: 929 ExecStart=/usr/sbin/firewalld --nofork --nopid $FIREWALLD_ARGS (code=exited, status=1/FAILURE)
Main PID: 929 (code=exited, status=1/FAILURE)
آوریل 07 05:36:17 server1.hamed1soleimani.ir systemd[1]: firewalld.service: main process exited, code=exited, status=1/FAILURE
آوریل 07 05:36:17 server1.hamed1soleimani.ir systemd[1]: Failed to start firewalld - dynamic firewall daemon.
آوریل 07 05:36:17 server1.hamed1soleimani.ir systemd[1]: Unit firewalld.service entered failed state.
and firewall-cmd status:
sudo firewall-cmd --stat
Traceback (most recent call last):
File "/bin/firewall-cmd", line 24, in <module>
from gi.repository import GObject
File "/usr/lib64/python2.7/site-packages/gi/__init__.py", line 37, in <module>
from . import _gi
ImportError: /usr/lib64/python2.7/site-packages/gi/_gi.so: undefined symbol: g_type_check_instance_is_fundamentally_a
I cant realize relation between firewalld and some gtk python extensions!
This worked for me:
systemctl stop firewalld
pkill -f firewalld
systemctl start firewalld
I know that it is an old thread , But I was facing this problem and I just fixed it, Figured it will help someone in the nearby future.
I thought the problem was in my code or that I mis placed the file.
Well , sadly This file is corrupted (perhaps misplaced)
/usr/lib/python2.7/site-packages/gi/_gi.so or I think it has been compiled badly.
What you need is to Update Glib 2 since it will overwrite & fix it , You can do this using yum
Try yum update glib2
I tested the above using CentOS Linux release 7.1.1503 (Core)
Cheers
The problem is your package /usr/lib/python2.7/site-packages/gi/_gi.so
Debian (python2) -> sudo apt install python-gi
Debian (python3) -> sudo apt install python3-gi
RedHat based systems -> yum install gilb2
Note : for OverWrite and fix you can use:
-> yum update glib2
You should try restarting the dbus service:
$ sudo systemctl restart dbus
$ sudo systemctl restart firewalld

Start a python script at boot on Ubuntu

I am new to python and have pretty basic knowledge of Linux.
I need to start a script at boot time on a Ubuntu 14.04.3 server.
The only thing is, the script is a monitoring tool and should be running all the time so I can't just make a periodical cron call.
I found this at first : running a python script with cron
I have tried to add this in crontab :
#reboot python /path/to/script.py &
And also this :
#reboot /path/to/script.py &
but it doesn't seems to work.
I have also seen this : How to make a python script run like a service or daemon in linux
The main answer is cron or a change in the python code.
So my question is : Is there another way to run my script at boot and let it run "forever" without changing the code ?
I assure you if I don't want to change the code it's not by lazyness but I will if it's the only option.
Other information (don't know if it's necessary), I am running Windows and have access to the server via PuTTY.
The version of Python is 2.7
UPDATE
Here is the cron log :
Nov 27 15:57:03 trustyovh cron[760]: (CRON) INFO (pidfile fd = 3)
Nov 27 15:57:03 trustyovh cron[798]: (CRON) STARTUP (fork ok)
Nov 27 15:57:03 trustyovh cron[798]: (CRON) INFO (Running #reboot jobs)
Nov 27 15:57:03 trustyovh CRON[807]: (administrateur) CMD (/home/administrateur/scuMonitor/main.py &)
Nov 27 15:57:03 trustyovh CRON[800]: (CRON) info (No MTA installed, discarding output)
Nov 27 16:09:01 trustyovh CRON[1792]: (root) CMD ( [ -x /usr/lib/php5/maxlifetime ] && [ -x /usr/lib/php5/sessionclean ] && [ -d /var/lib/php5 ] && /usr/lib/php5/sessionclean /var/lib/php5 $(/usr/lib/php5/maxlifetime))
Here is the crontab :
#reboot /home/administrateur/scuMonitor/main.py &
UPDATE 2
Well, it was actually working with the cron set to reboot, but, my script didn't put his log where I expected it to do (I wasn't understanding how the path work on Linux).
Thanks for all the answers everyone !
I would suggest you the same thing I have written here
Basically, you can run your python code as a service using systemd, all you have to do is to write a <your-app-name>.service file, like the one below
[Unit]
Description=Some kind of description
[Service]
Type=simple
ExecStart=<path to your bin with args if needed>
then, save it under /etc/systemd/system/. To check if everything is fine, run
sudo systemctl start <your-app-name>
and then
sudo systemctl status <your-app-name>
Finally run
sudo systemctl enable <your-app-name>
and the service will be executed at each system boot.
Taken from Run Python script at startup in Ubuntu.
You can start a service on Ubuntu by adding it to the /etc/init directory.
Put this in /etc/init
mystartupscript.conf
start on runlevel [2345]
stop on runlevel [!2345]
exec /path/to/script.py
As far as i know the only way to keep it checking for what ever you want it to check for is by implementing a loop in the code/daemonizing.

Categories

Resources