what does pkill -KILL -f java do? - linux

I am trying to understand what exactly each line of this code does:
cat << EOF > /tmp/kill_loop.sh
#!/bin/bash
while true;
do
pkill -KILL java
pkill -KILL python
sleep 1
done
EOF
nohup /bin/bash /tmp/kill_loop.sh &
but most importantly what pkill -KILL -f does

From the man page for pkill:
The pkill command searches the process table on the running system and
signals all processes that match the criteria given on the command line.
The -KILL argument is specifying which Linux process signal to send:
Signal name Signal value Effect
SIGHUP 1 Hangup
SIGINT 2 Interrupt from keyboard
SIGQUIT 3 Quit
SIGABRT 6 Abort
SIGKILL 9 Kill signal
SIGTERM 15 Termination signal - allow an orderly shutdown
SIGSTOP 17,19,23 Stop the process
See https://linux.die.net/man/1/pkill and https://linux.die.net/man/7/signal for more info.
Edit: In your example, java is being passed in as the pattern operand:
pattern -
Specifies an Extended Regular Expression for matching against the process names or command lines.

Related

How to catch SIGINT within a Bash subshell

If I run a command, such as grep, at the command line and hit ^C, the command is properly killed (with SIGINT I think). And if I run the grep in background and then run a kill SIGINT on its PID, it similarly gets terminated. But if I'm inside a script and run grep in background from the script, get its PID and then use 'kill -s SIGINT $PID', grep does not get killed. Why? If I use SIGTERM, instead of SIGINT, the kill does work.
#!/bin/bash
grep -rqa shazam /usr &
PID=$!
kill -s SIGINT $PID
Even if I put the grep in a subprocess, preceded by a SIGINT handler (in the subprocess), and hit the subprocess with SIGINT, the handler is not invoked.
#!/bin/bash
( trap 'echo "caught signal"' SIGINT; grep -rqa shazam /usr ) &
PID=$!
kill -s SIGINT $PID
The trap handler is invoked if I use SIGTERM, instead of SIGINT, but does not interrupt grep. If I add '/bin/kill -s SIGTERM 0' to the trap handler, there is an indication that the grep process gets terminated, but grep has already completed its work by then. I realize that Bash may have different default behaviors for the different signals, but I don't understand why my call to kill SIGINT is different than a ^C, why the trap call works for SIGTERM, but not for SIGINT, nor why SIGTERM isn't handled by the subprocess immediately.
Well, with further digging, I figured out 2 of my 3 questions. When I backgrounded grep within the script, the shell told it to ignore SIGINT. And Bash says it will wait to handle the signal until the subcommand is complete in some situations (which I don't fully follow at the moment), but the signal is handled immediately if hit the grep process directly with pkill.
"Actually bash will disable SIGINT (and SIGQUIT) on background processes and they can't be enabled" Background process and signals How SIGINT works
"Further background jobs are not supposed to be tied to the shell that started them. If you exit a shell, they will continue running. As such they shouldn't be interrupted by SIGINT, not by default. When job control is enabled, that is fulfilled automatically, since background jobs are running in separate process groups. When job control is disabled (generally in non-interactive shells), bash makes the asynchronous commands ignore SIGINT." Independent Program
Reason why SIGTERM works

How does pkill mask work?

If I have process named raspivid and process named raspivideo running and I execute command pkill raspvid, does it kill both processes or only process which is named raspvid?
If pkill kills both processes is there any linux-command to do the perfect match?
pkill kills all processes that command pgrep lists with the same parameters. In your case it sends SIGTERM signal to both processes.
The following command kills the exactly matching pattern only:
pkill -x raspivid

SIGINT in bash script

I have the following bash script.
#!/bin/bash
while :
do
sleep 2
infiniteProgramm -someParametrs
sleep 10
#in this line I need to stop my infiniteProgramm with bash command (SIGINT) (like Ctrl+C, but automatic)
clear
done
How can I send a SIGINT signal to my infiniteProgramm?
First: run infiniteProgram in the background:
infiniteProgram -someParameters &
Second: retrieve its PID from $!.
pid=$!
Third: kill it.
sleep 10
kill -2 $pid
2 corresponds to SIGINT, see kill -l for the list of all the signals.

bash: kill $$ not work?

The command kill $$ should kill current bash, but it seems that it doesn't work:
$ ps -p $$
PID TTY TIME CMD
18179 pts/4 00:00:00 bash
$ kill $$
$ ps -p $$
PID TTY TIME CMD
18179 pts/4 00:00:00 bash
Why?
I'm not sure why one would like to kill the current shell. Nevertheless...
kill PID would send SIGTERM when no signal is specified. bash ignores SIGTERM and SIGQUIT in the absence of any traps.
You'll achieve the desired effect if you were to say
kill -9 $$
or
kill -SIGKILL $$
Quoting from the manual:
When Bash is interactive, in the absence of any traps, it ignores
SIGTERM (so that ‘kill 0’ does not kill an interactive shell), and
SIGINT is caught and handled (so that the wait builtin is
interruptible). When Bash receives a SIGINT, it breaks out of any
executing loops. In all cases, Bash ignores SIGQUIT.
When you send a process any signal using kill command, the process can choose to handle the signal as per its wish. (There are a few signals, which cannot be handled.)
When you use kill $$, you are actually passing it signal=15 (SIGTERM). It can be handled by a process.
You can google for linux signal example to know HOW it is implemented.
& To answer YOUR question:
If you pass an un-handlable signal, like SIGKILL(9) or SIGSTOP(19), it will respectively kill/stop a running bash process.

Killing a terminal-attached process that doesn't respond to SIGINT, SIGQUIT

Sometimes both Ctr-C (SIGINT) and Ctrl-\ (SIGQUIT) are too weak. Is there a way to do an more aggressive kill (e.g. kill -9) on the currently-attached process using a quick keyboard shortcut?
If you are a zsh user, you can send SIGTERM with this in .zshrc
function terminate-current-job() { kill -s TERM %+ ; }
zle -N terminate-current-job terminate-current-job
bindkey "^T" terminate-current-job
That binds CTRLT to the previously defined widget/function.
If you are having problems with a specific command not responding to CTRL-C (because it ignores SIGINT, or because it asked the terminal driver to no longer recognise it as an interrupt character) , you can try wrapping it in rlwrap:
rlwrap -a -I <command>
rlwrap will catch the SIGINT sent by the terminal driver when you press CTRL-C and send a SIGTERM to <command> instead.
Of course, <command> may catch, or even ignore SIGTERM as well, but many commands that ignore SIGINT will respond to SIGTERM - while still being able to clean up before they terminate, in contrast to what happens when you use SIGKILL (kill -9)
Like proposed in the other answers, you can try to kill the process by catching some other signal. This can be also done with the linux bash built in trap command
that is used to execute a command when the shell receives any signal
To KILL your executable if SIGINT (CTRL-C) is captured, you need to start it like this:
yourexecutable & pid=$! ; trap 'echo KILL ; kill -9 $pid' INT ; echo WAIT $pid ; wait $pid ; echo DONE
Note that the echos are just for debugging purposes, they can simply be removed if you don't need them.

Resources