Why do my shell statements cause blocking? bash -c "ps ax | grep 'tcpdump' | grep -v grep | kill -9 $(awk '{print $1}')"
Question:
I am rewriting a function to alternate os.system() in Python to ensure that the output of the process is logged.
def log_system(self, cmd: str):
cmd = cmd.rstrip(' ')
if cmd[-1] == '&' and cmd[-2] != '&':
cmd = cmd[:-1]
# Redirects standard error to standard output for logging
executing = os.popen('bash -c ' + '"' + cmd + '"' + '>/dev/stdout 2>&1 &')
else:
executing = os.popen('bash -c ' + '"' + cmd + '"' + '>/dev/stdout 2>&1')
res = executing.readlines()
ret = executing.close()
if len(res) > 0: # print message if have some content
msg = ''.join(res)
if ret is None: # None means process return successfully
log.i(msg) # print stdout
else:
log.e(f'cmd execute failed: {cmd}n' + msg) # print stderr
The original statement works well and it is:
os.system("ps ax | grep 'tcpdump' | grep -v grep | kill `awk '{print $1}'` ")
After I use log_system(), the shell script could be:
bash -c "ps ax | grep 'tcpdump' | grep -v grep | kill `awk '{print $1}'`"
But, When I execute the code, it blocks, I don’t know what happened.
I use terminal to retry, this script is non-blocking:
ps ax | grep 'tcpdump' | grep -v grep | kill `awk '{print $1}'`
and this is also blocking:
bash -c "ps ax | grep 'tcpdump' | grep -v grep | kill -9 $(awk '{print $1}')"
bash -c "ps ax | grep 'tcpdump' | grep -v grep | kill `awk '{print $1}'`"
Answers:
The kill
command does not take process IDs on standard input, it must be supplied as an argument.
Specifically, your current command snippet (regardless of what goes into the kill
standard input) will hang forever because the awk
is waiting on its standard input (the terminal), effectively:
kill `awk '{print $1}'`
Hence the command would need to be something like:
kill $(ps ax | grep 'tcpdump' | grep -v grep | awk '{print $1}')
with the $()
capturing the standard output of its content and using that as a command line argument to kill
.
However, you may also want to look at one of my earlier answers. There are better tools available for finding and/or killing processes, such as pgrep
and pkill
. If you have those available to you, they’re usually a better option than trying to do it with ps/grep/awk
pipelines.
I am rewriting a function to alternate os.system() in Python to ensure that the output of the process is logged.
def log_system(self, cmd: str):
cmd = cmd.rstrip(' ')
if cmd[-1] == '&' and cmd[-2] != '&':
cmd = cmd[:-1]
# Redirects standard error to standard output for logging
executing = os.popen('bash -c ' + '"' + cmd + '"' + '>/dev/stdout 2>&1 &')
else:
executing = os.popen('bash -c ' + '"' + cmd + '"' + '>/dev/stdout 2>&1')
res = executing.readlines()
ret = executing.close()
if len(res) > 0: # print message if have some content
msg = ''.join(res)
if ret is None: # None means process return successfully
log.i(msg) # print stdout
else:
log.e(f'cmd execute failed: {cmd}n' + msg) # print stderr
The original statement works well and it is:
os.system("ps ax | grep 'tcpdump' | grep -v grep | kill `awk '{print $1}'` ")
After I use log_system(), the shell script could be:
bash -c "ps ax | grep 'tcpdump' | grep -v grep | kill `awk '{print $1}'`"
But, When I execute the code, it blocks, I don’t know what happened.
I use terminal to retry, this script is non-blocking:
ps ax | grep 'tcpdump' | grep -v grep | kill `awk '{print $1}'`
and this is also blocking:
bash -c "ps ax | grep 'tcpdump' | grep -v grep | kill -9 $(awk '{print $1}')"
bash -c "ps ax | grep 'tcpdump' | grep -v grep | kill `awk '{print $1}'`"
The kill
command does not take process IDs on standard input, it must be supplied as an argument.
Specifically, your current command snippet (regardless of what goes into the kill
standard input) will hang forever because the awk
is waiting on its standard input (the terminal), effectively:
kill `awk '{print $1}'`
Hence the command would need to be something like:
kill $(ps ax | grep 'tcpdump' | grep -v grep | awk '{print $1}')
with the $()
capturing the standard output of its content and using that as a command line argument to kill
.
However, you may also want to look at one of my earlier answers. There are better tools available for finding and/or killing processes, such as pgrep
and pkill
. If you have those available to you, they’re usually a better option than trying to do it with ps/grep/awk
pipelines.