This command does not work as expected:
$ python -V >> logfile.txt
The python version is displayed on screen, but does not end up in the logfile, what is needed to get it into the logfile?
$ python -V 2>> logfile.txt
python -V writes to stderr instead of stdout that's why you must append your append operator with 2.
the -V output is going to stderr, so you need to redirect it like this:
python -V 2>> logfile.txt
Related
Anyone can explain me why this
python -V | awk '{print $2}'
returns this
Python 2.7.5
instead of
2.7.5
What to do to return only the version number without "Python " ?
If you run
python -V >/dev/null
you will notice that you still get output! Apparently, python -V prints its output to stderr, not to stdout.
In a bourne-like shell, this should work:
python -V 2>&1 | awk '{print $2}'
How about using pure python command itself(I need to format it with dots in between though)
python -c 'import sys; print sys.version_info[0],sys.version_info[1],sys.version_info[2]'
OR as per Chris's comment use:
python -c 'import sys; print(".".join(map(str, sys.version_info[:3])))'
This question already has answers here:
Detect python version in shell script
(18 answers)
Closed 4 years ago.
I was trying to write a bash script to test the python version. However, I found python --version behave weirdly for python 2, as I can't process its output using any tool. I have tested the same script on Mac OS (10.13.5) and AWS Linux (GUN/Linux #1 SMP Fri Feb 16 00:18:48 UTC 2018). So I think the problem is related to python 2.
The script and corresponding output are:
$ echo $(python --version) | awk '{print $2}'
> Python 2.7.10
But the output should be 2.7.10.
$ echo $(python --version) > weird.txt
> Python 2.7.10
$ cat weird.txt
>
So the output cannot be written into a file as well.
The same script to test for python3 has a totally different result
$ echo $(python3 --version) | awk '{print $2}'
> 3.6.5
But python3's output can be written into a file.
$ echo $(python3 --version) > weird.txt
$ cat weird.txt
> Python 3.6.5
I have found the reason for this difference is that python --version does not output a normal string or whatsoever. Maybe it calls another command to output the result for it??? Thus the result cannot be caught by current process?? (just pure guess here)
Can anyone help me to figure out why there is the difference here? There are probably of million ways to test for python version. But I'm just super curious about what is happening here.
Thanks for all the replies. Just found a useful answer explaining that why python -V outputs to stderr:
Why does python print version info to stderr?
Python outputs the version to standard error (stderr) up to version 3.3 according to issue 18338 and as noted here, so redirect accordingly:
$ echo $(python --version 2>&1) | awk '{print $2}'
2.7.14
The command substitution is unnecessary and this could be written as:
$ python --version 2>&1 | awk '{print $2}'
How about using Python command itself using platform library of it(which is a very common in use).
python -c 'import platform; print(platform.python_version())'
When I run it I get Python's exact version.
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.
I've been wrestling with solutions from "How do I use sudo to redirect output to a location I don't have permission to write to?" and "append line to /etc/hosts file with shell script" with no luck.
I want to "append 10.10.10.10 puppetmaster" at the end of /etc/hosts. (Oracle/Red-Hat linux).
Been trying variations of:
subprocess.call("sudo -s", shell=True)
subprocess.call('sudo sh -c" "10.10.10.10 puppetmaster" >> /etc/hosts"', shell=True)
subprocess.call(" sed -i '10.10.10.10 puppetmaster' /etc/hosts", shell=True)
But /etc/hosts file stands still.
Can someone please point out what I'm doing wrong?
Simply use dd:
subprocess.Popen(['sudo', 'dd', 'if=/dev/stdin',
'of=/etc/hosts', 'conv=notrunc', 'oflag=append'],
stdin=subprocess.PIPE).communicate("10.10.10.10 puppetmaster\n")
You can do it in python quite easily once you run the script with sudo:
with open("/etc/hosts","a") as f:
f.write('10.10.10.10 puppetmaster\n')
opening with a will append.
The problem you are facing lies within the scope of the sudo.
The code you are trying calls sudo with the arguments sh and -c" "10.10.10.10 puppetmaster". The redirection of the >> operator, however, is done by the surrounding shell, of course with its permissions.
To achieve the effect you want, try starting a shell using sudo which then is given the command:
sudo bash -c 'sh -c" "10.10.10.10 puppetmaster" >> /etc/hosts"'
This will do the trick because the bash you started with sudo has superuser permissions and thus will not fail when it tries to perform the output redirection with >>.
To do this from within Python, use this:
subprocess.call("""sudo bash -c 'sh -c" "10.10.10.10 puppetmaster" >> /etc/hosts"'""", shell=True)
But of course, if you run your Python script with superuser permissions (start it with sudo) already, all this isn't necessary and the original code will work (without the additional sudo in the call):
subprocess.call('sh -c" "10.10.10.10 puppetmaster" >> /etc/hosts"', shell=True)
If you weren't escalating privileges for the entire script, I'd recommend the following:
p = subprocess.Popen(['sudo', 'tee', '-a', '/etc/hosts'],
stdin=subprocess.PIPE, stdout=subprocess.DEVNULL)
p.stdin.write(b'10.10.10.10 puppetmaster\n')
p.stdin.close()
p.wait()
Then you can write arbitrary content to the process's stdin (p.stdin).
I want to run a Python Interpreter as an inferior process in bash or zsh. During this time, I would like to send commands to the process and see the output in STDOUT. Something like this:
$ in=/dev/shm/python_test_in
$ out=/dev/shm/python_test_out
$ touch $in $out
$ python < $in > $out
$ echo print(1+1) > $in
$ cat $out
Sadly, this does not work. I am running GNU/Linux.
What you need is a pipe:
mkfifo ./in ./out
python < ./in > ./out &
echo "print(1+1)" > ./in
cat ./out
However, in this way, the python interpreter will quit immediately after this execution because it read an EOF in the "echo" line. I'm looking for the way to prevent the python interpreter from exiting on EOF.