Kill tftp command that's running in subshell - linux

I'm running the following command in Linux:
sudo ./tftpCommand &
where my executable tftpCommand file simply gets/puts a data file which sometimes does not exist.
I want to be able to stop the tftp command that was spawned in the subshell before it automatically times out.
Using something like kill $(jobs -p) shows that the subshell has been terminated but the tftp still runs -- I know this because several seconds later it prints to the shell that it can't find the file to transfer.
QUESTION: How do I ensure that the tftp command is killed alongside the subshell that runs it?
Thanks!

I've found a solution to my problem:
use pkill -c tftp to kill any current tftp commands.
I figured this out by using ps x -o "%p %r %c"
You can use a similar technique for any of the command names in the COMMAND column (corresponding to the %c and -c ) to kill other processes.
Hope that helps anyone else who stumbles upon the same problem!

Related

How to terminate an ssh command that was ran from a remote host?

I ran an ssh command doing the following: ssh user#remote "my command &". Now the process seems to be running in the background, but I cannot find it, and I want to end it. I've used netstat, but cannot find the process.
Didn't you expect it to run in the background? Thats what the & does. You can use ps af to show all of the processes running under your username. You can then kill it by PID.
Thanks everybody. I found the process doing ps aux. For some reason, the port that it was using wasn't being display in netstat.
I suggest some methods
sudo killall ssh
It may not be the best method to use this method, it is better to filter first and then close it
or
ps -o pid,cmd | grep ssh
kill -QUIT (pid)
To stop a program, send the QUIT signal.

How to find the PID of a running command in bash?

I've googled this question, but never found anything useful for my particular case.
So, what I'm trying to figure out is the PID of a certain command that is running so I can kill it if necessary. I know it's possible to get the PID of a command by typing echo $! So supposedly
my_command & echo $!
should give me the PID. But this isn't the case, and I think I know why:
My command is as follows:
screen -d -m -S Radio /path/to/folder -f frequency -r path/to/song
which opens a detached screen first and then types the command so that it gets executed and keeps on running in the background. This way the PID that echo shows me is the wrong one. I'm guessing it shows me PID of screen -d -m -S Radio /path/to/folder -f frequency -r path/to/song instead of the PID of the command run in the new terminal created by screen.
But there's another problem to it: when I run screen -ls in the terminal, the command that is running in the background doesn't show up! I'm fairly certain it's running because the Pi is constantly at 25% CPU usage (instead of the 0% or 1% usually) and when I type ps au I can actually see the command and the PID.
So now I'm calling the community: any idea on how I could find the PID of that certain command in the new terminal? I'm writing a bash script, so it has to be possible to obtain the PID through code. Perfect would be a command that stores the PID in a variable!
Thanks to #glennjackman I managed to get the PID I wanted with a simple pgrep search_word. At first it wasn't working, but somehow I made it work after some trial and error. For those wanting the PID on a variable, just type
pid=$(pgrep search_word)
Regarding the problem with screen -ls not showing my detached session, it's still not solved, but I'm not bothered with it. Thanks again for solving my problem #glennjackman !
EDIT:
Second problem solved, check the comments on berends answer.
You can easily find out all the running process and their PID by writing (for example):
ps aux
The process is run by screen so you can probably find it easier by writing:
ps aux | grep screen
For more info about ps and the parameters I used check (quick google) -> https://www.lifewire.com/g00/uses-of-linux-ps-command-4058715?i10c
EDIT: You can use this command with bash scripting as well.

Howto debug running bash script

I have a bash script running on Ubuntu.
Is it possible to see the line/command executed now without script restart.
The issue is that script sometimes never exits. This is really hard to reproduce (now I caught it), so I can't just stop the script and start the debugging.
Any help would be really appreciated
P.S. Script logic is hard to understand, so I can't to figure out why it's frozen by power of thoughts.
Try to find the process id (pid) of the shell, you may use ps -ef | grep <script_name>
Let's set this pid in the shell variable $PID.
Find all the child processes of this $PID by:
ps --ppid $PID
You might find one or more (if for example it's stuck in a pipelined series of commands). Repeat this command couple of times. If it doesn't change this means the script is stuck in certain command. In this case, you may attach trace command to the running child process:
sudo strace -p $PID
This will show you what is being executed, either indefinite loop (like reading from a pipe) or waiting on some event that never happens.
In case you find ps --ppid $PID changes, this indicates that your script is advancing but it's stuck somewhere, e.g. local loop in the script. From the changing commands, it can give you a hint where in the script it's looping.

Kill ssh or\and remote process from bash script

I am trying to run the following command as part of the bash script which suppose to open ssh channel, run the program on the remote machine, save the output to the file for 10 sec, kill the process, which was writing to the file and then give the control back to bash script.
#!/bin/bash
ssh hostname '/root/bin/nodes-listener > /tmp/nodesListener.out </dev/null; sshpid=!$; sleep 10; kill -9 $sshpid 2>/dev/null &'
Unfortunately, what it seems to be doing is starting the program: nodes-listener remotely, but it never gets any further and it doesn't give control to the bash script. So, the only way to stop the execution is to do Ctrl+C.
Killing ssh doesn't help (or rather can't be executed) since the control is not with bash script as it waits for the command within the ssh session to complete, which of course never happens as it has to be killed to stop.
Here's the command line that you're running on the remote system:
/root/bin/nodes-listener > /tmp/nodesListener.out </dev/null
sshpid=!$
sleep 10
kill -9 $sshpid 2>/dev/null &
You should change it to this:
/root/bin/nodes-listener > /tmp/nodesListener.out </dev/null & <-- Ampersand goes here
sshpid=$!
sleep 10
kill -9 $sshpid 2>/dev/null
You want to start nodes-listener and then kill it after ten seconds. To do this, you need to start nodes-listener as a background process, so that the shell which is executing this command line to move on to the next command after starting nodes-listener. The & in your command line is in the wrong place, and would apply only to the kill command. You need to apply it to the nodes-listener command.
I'll also note that your sshpid=!$ line was incorrect. You want sshpid=$!. $! is the process ID of the last command started in the background.
You need to place the ampersand after the first command, then put the remaining commands onto the next line:
ssh hostname -- '/root/bin/nodes-listener > /tmp/nodesListener.out </dev/null &
sshpid=$!; sleep 10; kill $sshpid 2>/dev/null'
Btw, ssh is returning after all commands had been executed. This does mean it will close the allocated pty as well. If there are still background jobs running in that shell session, they would being killed by SIGHUP. This means, you can probably omit the explicit kill command. (Depends on whether nodes-listener handles SIGHUP and SIGTERM differently). Having this, you could simplify the code to the following:
ssh hostname -- sh -c '/root/bin/nodes-listener > /tmp/nodesListener.out </dev/null &
sleep 10'
I have resolved this by pushing the shell script to the remote machine and executing it there. It is actually less tidy and relies on space being available on the remote computer.
Since my remote machine is a small physical device, the issue of the space usage is important (even for the tiny amount of space required in this case).
/root/bin/nodes-listener > /tmp/nodesListener.out </dev/null &
sshpid=!$
sleep 20
sync
# killing nodes-listener process and giving control back to the base bash
killall -9 nodes-listener 2>/dev/null && echo "nodes-listener is killed"

is it possible to create a non-child process inside a shell script?

I'm using a shell process pool API at Github, for a script, as below
function foobar()
{
mytask($1);
}
job_pool_init 100 0
tcpdump -i eth0 -w tempcap & #
for i in `seq 1 4`;do
mesg="hello"$i
job_pool_run foobar $mesg
sleep 5
done
job_pool_wait
pkill tcpdump #
echo 'all finish'
job_pool_shutdown
if I comment the tcpdump line,
then it works fine, as expected,
but when the tcpdump line is there,
There is a wait command in job_pool_wait, which waits for the ending of all children process, if there is no such a tcpdump line, it is as expected.
But I want to capture something until all the child processes finish, so I have to use a tcpdump. In this script, tcpdump process is a child process,
job_pool_wait will also wait for the ending of tcpdump process, which is not expected.
so a solution is to make tcpdump not a child process,
how can I do it,
or any other solutions?
thanks!
You should be able to run tcpdump in a sub-shell in the background:
(tcpdump -i eth0 -w tempcap &)
This should prevent it from appearing as a direct descendant of your script.
Answering your literal question, yes, run the command with exec. But I doubt that's what you really wanted.
I think what you really wanted is to be able to wait on specific pid. The wait command takes an optional pid. Either that round need to check when wait returns whether the process that just terminated is a process you're interested in, and wait again if it's not.

Resources