Sending Unix/Linux SIGNAL through PIPE - linux

I want to sent a SIGNAL to a process after .5 seconds.
Maybe this is not a good idea to do but I want to do it for an uncommon temporary case.
I tried like following, but its not working.
(sleep .5;kill -9)| some_process

Signals aren't directed to pipes; they're directed to process identifiers (pids). I might try something like this:
some_process & sleep .5; kill -KILL $!
which would run some_process in the background (that's what the & is for). After half a second, it will used the variable $! which indicates the pid of the last backgrounded process.
(Although sleep on some systems only accepts an integer.)

sleep .5; kill -9 $(pidof some_process) should work. pidof returns a process id for a process name. The $() returns the result of the command to the kill command. An alternative would be:
sleep .5; pidof some_process | xargs kill -9
check man pidof for details.
Edit: there is also timeout. timeout -s SIGKILL 0.5s some_process should do the trick if I understood your question correctly.

Related

In Bash, Kill background function will not kill internal process, why they have different pid?

For convenience, I put my server command into a function, but I background the function got a pid is not my server's pid.
myserver(){
# May contain complicate parameter
sleep 10
}
myserver > my.log &
pid=$!
ps aux|grep sleep
echo "Found PID " $pid is different from ps
So, if I kill $pid will not kill real server process(here is sleep).What should I do ?
UPDATE
sleep 10 &
pid=$!
ps aux|grep sleep
echo Found PID $pid is same
UPDATE
In this case
myserver(){
# May contain complicate parameter
sleep 10
}
myserver > my.log &
kill $!
Will kill the sleep process, but actually, my server is java -jar, when I do kill $!, the java process will not get killed.
In order to kill via the kill command you should provide the PID and not the Job Id.
Check this post about JID and PID
Update on Comment:
Are u sre you are providing it right?
In my system:
$ sleep 20 &
[2] 10080
$ kill -9 $!
[2]- Killed sleep 20
$
Folow up
Ok now I get it. Sorry i misinterpretted your question. What you describe is the expected behavior:
$! Expands to the decimal process ID of the most recent background command (see Lists) executed from the current shell. (For example, background commands executed from subshells do not affect the value of "$!" in the current shell environment.) For a pipeline, the process ID is that of the last command in the pipeline.
So in that case maybe try this proposed solution
Update on Question:
Ok, in the case of java proces I would try a regexp:
pkill -f 'java.*<your process name or some -classpath jar or something unique to the process you want to kill>'
In fact, any string or classpath jar that came along with this command and would result to a match would do the job.

syncing a shell script with kernel operations

For stopping activity in my embedded Linux system, I have the following shell script (interpreted by busybox):
#!/bin/sh
pkill usefulp_program
swapoff /home/.swapfile
umount -l /home
sleep 3 # While I can't find a way to sync, sleep
If I take off the sleep line, the script returns immediately, without waiting even for the umount (which is lazy, as for some reason it refuses to unmount otherwise). Do you know how can I wait for all the three operations to complete before finishing the script? Resorting to an arbitrary sleep does not look like a good solution.
Also, any hint on why I can not umount without the -l?
You need to wait for the killed process to terminate. As per your comment...
wait <pid>
...doesn't work! So, could loop ala:
while ps -p <pid> > /dev/null; do sleep 1; done
to wait for the killed process to terminate before doing the swapoff and umount.
As others already mentioned you should and only the -l when the process is terminated. An option if it takes long/it just ignores you polite request to stop itself is using a different signal. The option would be -9 to the kill/killall/pkill command to send the SIGKILL instead of SIGTERM. If you dont want to use the hammer on your first try you could do something like
pkill your_programm
sleep 10
pkill -9 your_programm

bash: run a command for n minutes, then SIGHUP it

Is there any bash/linux command to launch a long-running command, then kill it after n minutes? I guess I could hack something up with perl using fork and kill, but does anyone know of something already out there?
See the timeout command now in most GNU/Linux distros.
timeout -sHUP 10m command
The same functionality can be achieved with http://www.pixelbeat.org/scripts/timeout
Try it with this one, it starts your command in the background, stores it's PID in $P, waits for some time and kills it with a SIGHUP.
yourCommand & PID=$!
sleep ${someMinutes}m
kill -HUP $PID
Cheers
PS: that assumes a sleep that knows about Nm (minutes), else, you might want to do some math :)
n=5
some_command &
pid=$!
at now + $n minutes <<<"kill -HUP $pid"
The benefit of using at over waiting for sleep is that your script wont block waiting for the sleep to expire. You can go and do other things and at will asynchronously fire at the specified time. Depending on your script that may be a very important feature to have.

Sleep in a while loop gets its own pid

I have a bash script that does some parallel processing in a loop. I don't want the parallel process to spike the CPU, so I use a sleep command. Here's a simplified version.
(while true;do sleep 99999;done)&
So I execute the above line from a bash prompt and get something like:
[1] 12345
Where [1] is the job number and 12345 is the process ID (pid) of the while loop. I do a kill 12345 and get:
[1]+ Terminated ( while true; do
sleep 99999;
done )
It looks like the entire script was terminated. However, I do a ps aux|grep sleep and find the sleep command is still going strong but with its own pid! I can kill the sleep and everything seems fine. However, if I were to kill the sleep first, the while loop starts a new sleep pid. This is such a surprise to me since the sleep is not parallel to the while loop. The loop itself is a single path of execution.
So I have two questions:
Why did the sleep command get its own process ID?
How do I easily kill the while loop and the sleep?
Sleep gets its own PID because it is a process running and just waiting. Try which sleep to see where it is.
You can use ps -uf to see the process tree on your system. From there you can determine what the PPID (parent PID) of the shell (the one running the loop) of the sleep is.
Because "sleep" is a process, not a build-in function or similar
You could do the following:
(while true;do sleep 99999;done)&
whilepid=$!
kill -- -$whilepid
The above code kills the process group, because the PID is specified as a negative number (e.g. -123 instead of 123). In addition, it uses the variable $!, which stores the PID of the most recently executed process.
Note:
When you execute any process in background on interactive mode (i.e. using the command line prompt) it creates a new process group, which is what is happening to you. That way, it's relatively easy to "kill 'em all", because you just have to kill the whole process group. However, when the same is done within a script, it doesn't create any new group, because all new processes belong to the script PID, even if they are executed in background (jobs control is disabled by default). To enable jobs control in a script, you just have to put the following at the beginning of the script:
#!/bin/bash
set -m
Have you tried doing kill %1, where 1 is the number you get after launching the command in background?
I did it right now after launching (while true;do sleep 99999;done)& and it correctly terminated it.
"ps --ppid" selects all processes with the specified parent pid, eg:
$ (while true;do sleep 99999;done)&
[1] 12345
$ ppid=12345 ; kill -9 $ppid $(ps --ppid $ppid -o pid --no-heading)
You can kill the process group.
To find the process group of your process run:
ps --no-headers -o "%r" -p 15864
Then kill the process group using:
kill -- -[PGID]
You can do it all in one command. Let's try it out:
$ (while true;do sleep 99999;done)&
[1] 16151
$ kill -- -$(ps --no-headers -o "%r" -p 16151)
[1]+ Terminated ( while true; do
sleep 99999;
done )
To kill the while loop and the sleep using $! you can also use a trap signal handler inside the subshell.
(trap 'kill ${!}; exit' TERM; while true; do sleep 99999 & wait ${!}; done)&
kill -TERM ${!}

Limiting the time a program runs in Linux

In Linux I would like to run a program but only for a limited time, like 1 second. If the program exceeds this running time I would like to kill the process and show an error message.
Ah well. timeout(1).
DESCRIPTION
Start COMMAND, and kill it if still running after DURATION.
StackOverflow won't allow me to delete my answer since it's the accepted one. It's garnering down-votes since it's at the top of the list with a better solution below it. If you're on a GNU system, please use timeout instead as suggested by #wRAR. So in the hopes that you'll stop down-voting, here's how it works:
timeout 1s ./myProgram
You can use s, m, h or d for seconds (the default if omitted), minutes, hours or days. A nifty feature here is that you may specify another option -k 30s (before the 1s above) in order to kill it with a SIGKILL after another 30 seconds, should it not respond to the original SIGTERM.
A very useful tool. Now scroll down and up-vote #wRAR's answer.
For posterity, this was my original - inferior - suggestion, it might still be if some use for someone.
A simple bash-script should be able to do that for you
./myProgram &
sleep 1
kill $! 2>/dev/null && echo "myProgram didn't finish"
That ought to do it.
$! expands to the last backgrounded process (through the use of &), and kill returns false if it didn't kill any process, so the echo is only executed if it actually killed something.
2>/dev/null redirects kill's stderr, otherwise it would print something telling you it was unable to kill the process.
You might want to add a -KILL or whichever signal you want to use to get rid of your process too.
EDIT
As ephemient pointed out, there's a race here if your program finishes and the some other process snatches the pid, it'll get killed instead. To reduce the probability of it happening, you could react to the SIGCHLD and not try to kill it if that happens. There's still chance to kill the wrong process, but it's very remote.
trapped=""
trap 'trapped=yes' SIGCHLD
./myProgram &
sleep 1
[ -z "$trapped" ] && kill $! 2>/dev/null && echo '...'
Maybe CPU time limit (ulimit -t/setrlimit(RLIMIT_CPU)) will help?
you could launch it in a shell script using &
your_program &
pid=$!
sleep 1
if [ `pgrep $pid` ]
then
kill $pid
echo "killed $pid because it took too long."
fi
hope you get the idea, I'm not sure this is correct my shell skills need some refresh :)
tail -f file & pid=$!
sleep 10
kill $pid 2>/dev/null && echo '...'
If you have the sources, you can fork() early in main() and then have the parent process measure the time and possibly kill the child process. Just use standard system calls fork(), waitpid(), kill(), ... maybe some standard Unix signal handling. Not too complicated but takes some effort.
You can also script something on the shell although I doubt it will be as accurate with respect to the time of 1 second.
If you just want to measure the time, type time <cmd ...> on the shell.
Ok, so just write a short C program that forks, calls execlp or something similar in the child, measures the time in the parent and kills the child. Should be easy ...

Resources