I read a lot of examples with same problem but I didn't solve it. I have a small python app that runs some bash commands. Most of lines are bash shell commands. App has some bash shell variables that I need them to pass outside from bash shell to python part file. I want start
and end
variables to pass outside of part bash shell. I have to say that I write python3 count.py enp35s0
to run my python app.
How can I do that?
I am sorry for my English, I am not native speaker.
#!/usr/bin/python3
import os
import sys
import subprocess
import time
if len(sys.argv) > 1:
n = sys.argv[1]
def capture():
subprocess.run(['/bin/bash', '-c', bash, n], check=True)
bash = '''
#!/usr/bin/env bash
#set -x
INTERVAL="1" # update interval in seconds
n='''+n+'''
# How many time script will work.
start=1
end=2 # put the number for minues. 3600 is 1 hour.
#end=$(( 1 * 2700 ))
while [[ $start -le $end ]]
do
#echo "$start"
((start = start + 1))
# Capture packets.
R1=`cat /sys/class/net/$n/statistics/rx_bytes`
T1=`cat /sys/class/net/$n/statistics/tx_bytes`
sleep $INTERVAL
R2=`cat /sys/class/net/$n/statistics/rx_bytes`
T2=`cat /sys/class/net/$n/statistics/tx_bytes`
TBPS=`expr $T2 - $T1`
RBPS=`expr $R2 - $R1`
TKBPS=`expr $TBPS / 1024`
RKBPS=`expr $RBPS / 1024`
echo "TX $1: $TKBPS kB/s RX $1: $RKBPS kB/s"
# Sum number of packets sent and received on an interface
SUM=$(expr $RKBPS)
# If there is internet traffic, reset count to zero.
if (( $SUM >= 10 ));then
((i = 0))
echo "Connection is active:"
fi
now=$(( $SUM ))
max=$((sum>max?sum:max))
if [ $now -gt $max ] ; then
max=$now
fi
wget -q --spider http://example.com
if [ $? -eq 0 ]; then
echo "Online"
((no_internet = 0 ))
else
# echo "Offline"
no_internet=$(( no_internet+1 ))
fi
if [ $no_internet -gt 10 ] ; then
echo "off"
/sbin/shutdown -h now
fi
echo "The SUM is: $SUM"
echo "The maximum download bandwidth is: $max"
#echo
echo $start "Seconds" 'of' $end "Seconds until end"
done
# When script reach here then will shutdown the system.
/sbin/shutdown -h now
'''
capture()
#-----HERE I WANT TO PUT 2 VARIABLES
#start variable
start= #----result from bash shell script above
#end variable
end= #----result from bash shell script above
Try this:
#!/usr/bin/env python3
import os
import sys
import subprocess
def get_n() -> str:
if len(sys.argv) > 1:
n = sys.argv[1]
else:
n = input('Please input `n`: ')
return n
## ----STARTING BASH SHELL----
BASH = '''
#!/usr/bin/env bash
INTERVAL="1" # update interval in seconds
n={}
# How many time script will work.
start=1
end=1800 # put the number for minues. 3600 is 1 hour.
while [[ $start -le $end ]]
do
.....
.....
.....
echo $start "Seconds" 'of' $end "Seconds until end"
'''
## ----END OF BASH SHELL
def capture(n, bash=BASH) -> str:
return subprocess.run(bash.format(repr(n)), shell=True, check=True, capture_output=True).stdout.strip().decode()
def main():
ret = capture(get_n())
print('Output of bash result:\n'+ret)
if __name__ == '__main__':
main()
Updated Answer
Here's a bash script called script.sh
that accepts 2 parameters and outputs each parameter doubled:
#!/bin/bash
p1=$1
p2=$2
((result1=p1*2))
((result2=p2*2))
echo "${result1} ${result2}"
Now call it from Python and get the results:
import subprocess
sp = subprocess.run(["./script.sh","1","5"], capture_output=True)
result1, result2 = sp.stdout.split()
print(result1, result2) # prints 2, 10
Original Answer
If you want to pass values into a script that you execute, you have the following options:
stdin
Let's look at each in turn...
You call your script with command-line parameters like this:
./SomeScript a "another param"
or, if the caller is Python:
sp = subprocess.run(["./SomeScript", "a", "another param"])
Then, inside the called script, you access the parameters like this:
#!/bin/bash
param1="$1"
param2="$2"
echo "First param: $param1, second param: $param2"
Or, if the called script is Python:
import sys
print(sys.argv[1:])
You set an environment variable before starting the script, using either of these methods:
export name="Simon"
./SomeScript
or:
name="Simon" ./SomeScript
or, if the caller is Python:
import os
os.environ['name'] = 'Simon'
Then, inside the script, you can access $name
:
#!/bin/bash
echo "name is $name"
or, if the called script is Python:
import os
print(os.environ['name'])
stdin
You send some value to the script on its stdin
using one of these methods:
printf "Simon" | ./SomeScript
or, using a bash
"here-string" :
./SomeScript <<< "Simon"
Then, inside your script, you read the value from stdin
into a variable with:
#!/bin/bash
read -r name
Or, if the called script is Python:
#!/usr/bin/env python3
v = input()
print(f'Read from stdin: {v}')
Note that you could equally read from sys.stdin
or other methods.
Other ways of passing values into scripts include letting them read from a disk file, or a database, or Redis , or a socket, or a message queue...
Here's an example with Redis which lets you share strings, atomic integers, hashes, lists, queues, images, sets and other data structures between different processes - even in different machines. First, one script puts a value into Redis :
redis-cli set name "Simon"
then any other process (whether bash
, Python
, PHP
, Rust
) on any machine, can retrieve the value with:
redis-cli get name
If you want to access the output from a script you called, you have the following options:
Let's look at each in turn.
The script prints something on its stdout
, or stderr
like this:
#!/bin/bash
printf "Some result"
>&2 printf "Some error"
And the caller, if bash
can pick it up like this:
#!/bin/bash
result=$( ./SomeScript )
Or, if the caller is Python, it can catch the output from subprocess.run()
.
sp = subprocess.run(["./SomeScript"], capture_output=True)
print(sp.stdout, sp.stderr)
The script exits with an exit status like this:
#!/bin/bash
exit 3
And the caller, if bash
can pick it up like this:
#!/bin/bash
./SomeScript
status=$?
Or, if the caller is Python, it can catch the exit status from subprocess.run()
.
sp = subprocess.run(["./SomeScript"], capture_output=True)
print(sp.returncode)
As before, the called script can write to a file on disk, or a database, or a socket, or a message queue, or Redis as above.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.