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 end
variable to pass outside of part bash shell.
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
if len(sys.argv) > 1:
n = sys.argv[1]
def capture():
subprocess.run(['/bin/bash', '-c', bash, n], check=True)
## ----STARTING BASH SHELL----
bash = '''
#!/usr/bin/env bash
INTERVAL="1" # update interval in seconds
n=''' 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
capture()
#end variable above from bash shell part I need put here.
CodePudding user response:
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(['/bin/bash', '-c', bash.format(repr(n))], check=True, capture_output=True).stdout
def main():
ret = capture(get_n())
print('Output of bash result:\n' ret)
if __name__ == '__main__':
main()
CodePudding user response:
If you want to pass values into a script that you execute, you have the following options:
- Command-line parameters
- environment variables
stdin
- file or some other method
Let's look at each in turn...
Command-line parameters
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:])
Environment variables
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'])
via 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.
via file or some other method
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:
- printed result
- exit status
- text file, or database, or other app
Let's look at each in turn.
printed result
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)
exit status - mostly just for true/false outputs
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)
file output
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.