Passing arguments to python interpreter from bash script - python

Sorry this is a very newbie question, but I just can't seem to get it to work.
in my bash script, I have
python=/path/to/python
script=$1
exec $python $script "$#"
How would I pass an argument, say -O to the python interpreter? I have tried:
exec $python -O $script "$#"
And have tried changing python variable to "/path/to/python -O", as well as passing -O to the script, but every time i do any of these three, I get import errors for modules that succeed when I remove the -O.
So my question is how to tell the python interpreter to run with -O argument from a bash script?
Thanks.

You should shift your positional parameters to the left by 1 to exclude your script which is in the first arguments from being included to the arguments for python.
#!/bin/sh
python=/path/to/python
script=$1; shift
exec "$python" -O "$script" "$#"
Then run the script as bash script.sh your_python_script arg1 arg2 ... or sh script.sh your_python_script arg1 arg2 ....

Related

Best way to run script via a /bin/bash shell script in multiple environments?

I have a python script which I run on localhost and development in command line with argument, sth as python script.py development - on development and python script.py localhost - on localhost.
Now I want to run this script - when I running script /bin/bash sh,
so I want to run this script from /bin/.bash script.
I added in headers in sh script: #!/usr/bin/env python.
In what way I can achieve this?
do
if [ $1 == "local" ]; then
python script.py $1
elif [ $1 == "development" ]; then
python script.py $1
What I can do to improve this script?
Since $1 already contains what you want, the conditional is unnecessary.
If your script is a Bash script, you should put #!/bin/bash (or your local equivalent) in the shebang line. However, this particular script uses no Bash features, and so might usefully be coded to run POSIX sh instead.
#!/bin/sh
case $1 in
local|development) ;;
*) echo "Syntax: $0 local|development" >&2; exit 2;;
esac
exec python script.py "$1"
A more useful approach is to configure your local system to run the script directly with ./script.py or similar, and let the script itself take care of parsing its command-line arguments. How exactly to do that depends on your precise environment, but on most U*x-like systems, you would put #!/usr/bin/env python as the first line of script.py itself, and chmod +x the file.
I assume this is what you wanted...
#!/bin/bash
if [ ! "$#" ]; then
echo "Usage: $1 (local|development) "
exit
fi
if [ "$1" == "local" ]; then
python script.py "$1"
echo "$1"
elif
[ "$1" == "development" ]; then
python script.py "$1"
echo "$1"
fi
Save the bash code above into a file named let's say script.sh. The make it executable: chmod +x script.sh. Then run it:
./script.sh
If no argument is specified, the script will just print an info about how to use it.
./script.sh local - executes python script.py local
./script.sh development - executes python script.py development
You can comment the lines with echo, they were left there just for debugging purposes (add a # in front of the echo lines to comment them).

Using Python to run a sourced script, cd, and then run a command within the SAME shell

How can run a sourced bash script, and then change directories, and then run a command, all within the same shell (Using python)? Is this even possible?
My Attempt:
subprocess.check_call(["env -i bash -c 'source ./init-build ARG'", "cd ../myDir", "bitbake myBoard"], shell =True)
I would make this for you, but I need to see the absolute paths. Here is an example
subprocess.check_call(["""/usr/bin/env bash -c "cd /home/x/y/tools && source /home/x/y/venv/bin/activate && python asdf.py" >> /tmp/asdf.txt 2>&1"""], shell=True)

How to pipe output from a linux command to a python script?

We have a python script that accepts the following arguments as example:
mypie.py --size=20 --pielist='{"apple":[5],"orange":[7]}' --quantity=10
We tried in our test.sh bash shell script:
test.sh 20 5 7 10
test.sh
export SIZE=$1
export APPLE=$2
export ORANGE=$3
export QUANTITY=$4
echo "--size=$SIZE" --pipelist='{\"apple\":[$2],\"orange\":[$3]}\"' --quantity=$4" | tee output.txt
cat output.txt | sudo python mypie.py
We got error
ERROR: size is not specified.
but when we cat output.txt, we can see that it is there with size value.
--size=20 --pielist='{"apple":[5],"orange":[7]}' --quantity=10
What are we doing wrong ?
Thanks
This would do -
cat output.txt | sudo xargs python mypie.py
Using the pipe redirects the content to stdin of the program - not the command line.
You could consider building up an args variable - then passing that to both the output.txt, and your python script.
For example:
export SIZE=$1
export APPLE=$2
export ORANGE=$3
export QUANTITY=$4
export ARGS="--size=$SIZE" --pipelist='{\"apple\":[$2],\"orange\":[$3]}\"' --quantity=$4"
echo $ARGS | tee output.txt
sudo python mypie.py $ARGS
You can use command substitution to directly place the output of command as the arguments to your python program.
python mypie.py `cat output.txt`
or
python mypie.py $(cat output.txt)
The simple and obvious solution is to change test.sh so that it passes the parameters correctly.
#!/bin/sh
set -x # if you want to see the script's parameters
sudo python mypie.py --size="$1" \
--pipelist="{'apple':[$2],'orange':[$3]}" --quantity="$4"
Passing the arguments as standard input (which is what a pipe does) is simply not how it is usually done, nor a particularly suitable model for this particular type of interaction.

Executing output of python from loop in bash

I wrote a bash that has python command included in loop: (part of script)
#!/bin/bash
ARG=( $(echo "${#:3}"))
for (( i=1; i<=$#-3; i++ ))
do
python -c "print('<Command with variables>' * 1)"
done
When I run it, depends on number of my args for example I have this output:
nohup command-a &
nohup command-b &
nohup command-c &
How do I execute the output lines from bash immediately?
Can I tell python command to run them in each iteration? How?
Thank you
You can achieve that by executing the python code in a sub-shell and evaluating the content of that shell afterwards.
eval $(python -c ...)
$() returns a string you can evaluate with eval
You are asking two questions. I can only answer the first one:
If you want to run commands coming to the standard output, just redirect them to bash:
python -c 'print "ls"' | bash

Changing Process Name using Shell for nagios monitoring with check_procs

I have a python script to start a process which I want to monitor using Nagios. When I run that script and perform ps -ef on my ubuntu EC2 instance, it shows process as python <filename>.py --arguments. For Nagios to monitor that process using check_procs, we need to supply process name. Here process name becomes 'python'.
/usr/lib/nagios/plugins/check_procs -C python
It returns the output that one python process is running. This is fine when I'm running one python process. But If I'm running multiple python scripts and monitor only few, then I have to give that particular process name. If in the above command, I give python script name, it throws an error. So I want to mask whole python <filename>.py --arguments to some other name so that while performing check_procs, I can give that new name.
If anyone have any idea, please let me know. I have checked other stackoverflow questions which suggest changing python process name using setproctitle but I want to perform it using shell.
Regards,
Sanket
You can use the check_procs command to look at arguments, which includes the module name. The following command will let you know if the python module 'module.py' is running.
/usr/lib/nagios/plugins/check_procs -c 1:1 -a module.py -C python
The -c argument lets you set the critical range. 1:1 will trigger a critical status if there is more or less than 1 process that matches running.
The -a argument will filter based on processes that contain the args 'module.py' (change it to the name of the module you want to monitor)
The -C argument will make sure that the process is a python process
If you need help figuring out how to create the service definition, I had to figure that out too. Just let me know.
REFERENCE:
check_procs plugin manpage
http://nagiosplugins.org/man/check_procs
You can't change the process name from pure Python, although you can use a wrapper (for example, written in C) to do so.
However, what you should do instead is making your program a daemon, and using a pidfile. Have a look at the python Daemon API and its implementation python-daemon.
check_procs already handles this situation.
check_procs can tell the difference between scripts launched as an argument to the interpreter vs jobs run directly a hashbang interpreter. Even though both of these look the same in the ps output!! The latter case will not be listed in check_procs -C python!
If you run your scripts explicitly via python: python <filename.py>, then you can monitor them with the check_procs -C python -a filename.py.
If you put #!/usr/bin/python in your scripts and run them as ./filename.py, then you can monitor with check_procs -C filename.py.
Example command line session showing this behavior:
#make test.py directly executable. See code below
$ chmod a+x test.py
#launch via python explicitly:
$ /usr/bin/python ./test.py &
[1] 27094
$ check_procs -C python && check_procs -C test.py && check_procs -a test.py
PROCS OK: 1 process with command name 'python'
PROCS OK: 0 processes with command name 'test.py'
PROCS OK: 1 process with args 'test.py'
#launch via python implicitly
$ ./test.py &
[2] 27134
$ check_procs -C python && check_procs -C test.py && check_procs -a test.py
PROCS OK: 1 process with command name 'python'
PROCS OK: 1 process with command name 'test.py'
PROCS OK: 2 processes with args 'test.py'
#PS 'COMMAND' output looks the same
$ ps 27094 27134
PID TTY STAT TIME COMMAND
27094 pts/6 S 0:00 /usr/bin/python ./test.py
27134 pts/6 S 0:00 /usr/bin/python ./test.py
#kill the explicit test
$ kill 27094
[1] - terminated /usr/bin/python ./test.py
$ check_procs -C python && check_procs -C test.py && check_procs -a test.py
PROCS OK: 0 processes with command name 'python'
PROCS OK: 1 process with command name 'test.py'
PROCS OK: 1 process with args 'test.py'
#kill the implicit test
$ kill 27134
[2] + terminated ./test.py
$ check_procs -C python && check_procs -C test.py && check_procs -a test.py
PROCS OK: 0 processes with command name 'python'
PROCS OK: 0 processes with command name 'test.py'
PROCS OK: 0 processes with args 'test.py'
test.py is a python script that sleeps for 2 minutes. It is chmod +x and has a hashbang #! line invoking /usr/bin/python.
#!/usr/bin/python
import time
time.sleep(120)
Create a pid file and use that file for the process lookup with nagios.
I'm not saying this is the best solution (it wouldn't scale well at all), but you can create a symbolic link to the python command and execute your script using this link. e.g.
ln -s `which python` ~/mypython
~/mypython myscript.py
Scripts launched using the link should show up as mypython in ps.
You can use subprocess.Popen to change the executable name, but you'd have to use a wrapper script (or some weird fork magic). The following code causes ps to list the executable as kwyjibo /tmp/test.py instead of /usr/bin/python /tmp/test.py:
import subprocess
p = subprocess.Popen(['kwyjibo', '/tmp/test.py'], executable='/usr/bin/python')

Categories