I need to execute my python program from shell script so that the print commands in my python program will be exposed for reading from another program.
the shell script:
#!/bin/bash
if [ $# -lt 1 ] || [ $# -gt 2 ];then
echo "Usage: $0 APK <duration in seconds>"
exit 1;
fi
printf "$(python '/root/Desktop/DroidBox_4.1.1/scripts/droidbox.py' $1 $2 -c 'import sys; exec sys.stdin.read()')"
My python program should get the parametrs $1 and $2 but it doesn't recognize those as parametrs but taking -c and the command after it as the parametrs.
For answers like: getting the process input stream in my other project won't work for me. the only way that seems to be working is to use -c option and the command 'exec sys.stdin.read()'.
thank you.
It should work pretty well just the way you've written it. In a stripped down version here's what I get:
the (bash) test.sh script:
#!/bin/bash
python /tmp/test.py $1 $2
the (python) test.py script:
import sys
print "in python"
print sys.argv
and finally a shell session:
smassey#hacklabs:/tmp $ ./test.sh hello world
in python
['/tmp/test.py', 'hello', 'world']
As you can see, the bash script calls the python script which prints values to stdout so they're just as exposed as anything else directed to stdout:
smassey#hacklabs:/tmp $ ./test.sh hello world | grep python | tr 'a-z' 'A-Z'
IN PYTHON
The argparse module is very helpful as well. This allow you to add custom flags to your program (makes it more convenient to works with from a user's perspective as well).
Related
In My shell scripts1, It works.:
test1.sh
python main.py
if [[ $? -ne 0 ]]
then
exit
fi
test2.sh
python main.py 2>&1 | tee log.txt
if [[ $? -ne 0 ]]
then
exit
fi
Script 2 is failed. How could I get the return code of python-call main in test2.sh?
If you use more commands in one line, you need to use the PIPESTATUS to get the proper return code for each command.
For example:
Python code:
import sys
def exit_with_code():
sys.exit(5)
exit_with_code()
Shell script:
python3 test.py 2>&1 | tee log.txt
echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
Output:
5 0
It means the return code of Python script is 5 and the return code of tee is 0.
You tagged your question for POSIX Shell, and AFIK, there is no way to achieve this in a POSIX Shell. However, many other shells do have a feature, which allow this.
For instance, if you could use bash, you can use PIPESTATUS, as was suggested here already. If you go for Zsh, there is a similar array named pipestatus.
If you want to go for ksh, you don't have an equivalent feature, but here is a discussion how to deal with this problem in Korn Shell.
You can do the redirection outside of the if and also avoid the antipattern.
if ! python main.py; then
exit
fi 2>&1 | tee log.txt
(See Why is testing "$?" to see if a command succeeded or not, an anti-pattern?)
I found it here: https://netsec.ws/?p=337
echo os.system('/bin/bash')
os.system is from python but echo is not, I think... what language is this exactly?
If you looked at the echo tag, you'll see its description: "Simple function outputting text. Exists in script languages.", if you're running Linux or Mac and even Windows Command Prompt you can enter this:
$ echo Hello shell world
Output:
Hello shell world
echo is useful for testing shell glob expansion, echoing the values of environment variables and sending output to stdins of other programs, for example try this with Bash:
$ echo 'print("Spam" * 2)' | python -
Output:
SpamSpam
And this:
$ echo 'import os; os.system("echo SPAM")' | python -
Output:
SPAM
Consider this:
$ cat test.py
import sys
print "Doing something ..."
sys.exit(1)
$ python test.py
Doing something ...
$ echo $?
1
$ python test.py | tee log # used in Jenkins, but I need to capture rc of 1 as well
Doing something ...
$ echo $?
0
As you can see I am unable to capture the return code of 1 from the python script if I pipe the output to tee. Is there a way I can accomplish this ? This code is in Build->execute shell section in Jenkins.
Since I am unable to capture the rc of 1 the commands following the line continue to get executed, which I don't want to happen.
In bash you can use the PIPESTATUS array to get the exit status of each command in a pipeline:
python test.py | tee log
echo ${PIPESTATUS[0]}
Regarding "Since I am unable to capture the rc of 1 the commands following the line continue to get executed", you can add set -o errexit and set -o pipefail to the start of your script, it will then terminate directly if you get an error (even inside a piped command). Here a good resource with a more in-depth explanation.
I've created a simple init script for an application I'm building. The start part of the script looks like this:
user="ec2-user"
name=`basename $0`
pid_file="/var/run/python_worker.pid"
stdout_log="/var/log/worker/worker.log"
stderr_log="/var/log/worker/worker.err"
get_pid() {
cat "$pid_file"
}
is_running() {
[ -f "$pid_file" ] && ps `get_pid` > /dev/null 2>&1
}
case "$1" in
start)
if is_running; then
echo "Already started"
else
echo "Starting $name"
cd /var/lib/worker
. venv/bin/activate
. /etc/profile.d/worker.sh
python run.py >> "$stdout_log" 2>> "$stderr_log" &
echo $! > "$pid_file"
if ! is_running; then
echo "Unable to start, see $stdout_log and $stderr_log"
exit 1
fi
echo "$name running"
fi
I'm having trouble with this line:
python run.py >> "$stdout_log" 2>> "$stderr_log" &
I want to start my application with this code and redirect the outputs to the files specified above. However, when I include the & to make it run in the background, nothing appears in the two log files. BUT, when I remove the & from this line, the log files get data. Why is this happening?
Obviously I need to run the command to make it run as a background process in order to stop the shell waiting.
I am also sure that the process is running when I use the &. I can find it with a ps -aux :
root 11357 7.0 3.1 474832 31828 pts/1 Sl 21:22 0:00 python run.py
Anyone know what I'm doing wrong? :)
Anyone know what I'm doing wrong? :)
Short Answer:
Yes. add -u to the python command and it should work.
python -u run.py >> "$stdout_log" 2>> "$stderr_log" &
Long Answer:
It's a buffering issue (from man python):
-u Force stdin, stdout and stderr to be totally unbuffered. On systems where it matters, also put stdin, stdout
and stderr in binary mode. Note that there is internal buffering in xreadlines(), readlines() and file-
object iterators ("for line in sys.stdin") which is not influenced by this option. To work around this, you
will want to use "sys.stdin.readline()" inside a "while 1:" loop.
Every now and then I need to get the answer to a calculation. As I usually have a terminal screen open that is a natural place for me to ask such mathematical questions.
The Python interactive shell is good for this purpose, provided you want to enter yet another shell only to have to exit out of it later on.
Sometimes though it is preferable to have the answer immediately available from the command line. Python has the -c command option that I found to be useful in processing a single command and returning the result. I wrote the following bash shell script to utilize it:
#!/bin/bash
# MHO 12-28-2014
#
# takes a equation from the command line, sends it to python and prints it
ARGS=0
#
if [ $# -eq 1 ]; then
ARGS=1
fi
#
if [ $ARGS -eq 0 ]; then
echo "pc - Python Command line calculator"
echo "ERROR: pc syntax is"
echo "pc EQUATION"
echo "Examples"
echo "pc 12.23+25.36 pc \"2+4+3*(55)\""
echo "Note: if calculating one single equation is not enough,"
echo "go elsewhere and do other things there."
echo "Enclose the equation in double quotes if doing anything fancy."
echo "m=math module ex. \"m.cos(55)\""
exit 1
fi
#
if [ $ARGS -eq 1 ]; then
eqn="$1"
python -c "import math; m=math; b=$eqn; print str(b)"
fi
#
Example Output
$ pc 1/3.0
0.333333333333
$ pc 56*(44)
2464
$ pc 56*(44)*3*(6*(4))
177408
$ pc "m.pi*(2**2)"
12.5663706144
Question, keeping in mind python -c option, is there any concise way to implicitly refer to the math module so that the last pc command might be formatted as pc "pi*(2**2)" ?
You can use
from math import *
to import all constants and functions from the math module into your global scope.
if [ $ARGS -eq 1 ]; then
eqn="$1"
python -c "from math import *; b=$eqn; print str(b)"
fi
$ pc "pi*(2**2)"
12.5663706144
Excellent! Thanks!