0

I'm using pkill to send USR2 signal to suricata by python subprocess as below:

#!/usr/bin/python3

script_command='pkill -SIGUSR2 -f /usr/bin/suricata'
exit_status = subprocess.call(script_command, env=self.config_environment, shell=True)

the result is: exit_status = -12

When I executed on terminal:

pkill -SIGUSR2 -f /usr/bin/suricata
echo $?

the result is: 0

As I understand the document said at https://docs.python.org/3/library/subprocess.html#subprocess.CompletedProcess.returncode

Does Python detect return code of pkill process or suricata process is 12?

How can I bypass this mechanism and force subprocess.call return 0 when pkill send USR2 to suricata successfully and negative exit code corresponding to pkill process's feedback?

1 Answers1

2

The documentation you've linked says

A negative value -N indicates that the child was terminated by signal N (POSIX only).

This implies that the process run by subprocess.call() was killed by SIGUSR2 (since SIGUSR2 is 12).

Since you're using shell=True, there will be a process with the command line sh -c '... suricata', which will be matched by pkill -f (since -f means The pattern is normally only matched against the process name. When -f is set, the full command line is used.).

You may want to do

ret = subprocess.call([
  shutil.which("pkill"),
  "-SIGUSR2",
  "-f",
  "/usr/bin/suricata",
])

to avoid the additional shell process.

Better yet, you could use e.g. psutil to find the Suricata process and kill it.

EDIT

From the comments:

However pkill -SIGUSR2 -F /var/run/suricata.pid is enough

If you have a pidfile at hand, you don't need pkill for anything...

import os
import signal

with open("/var/run/suricata.pid", "r") as pidfile:
  pid = int(pidfile.read().strip())
  os.kill(pid, signal.SIGUSR2)
AKX
  • 152,115
  • 15
  • 115
  • 172
  • How can I force python confirm result of `pkill` not `suricata`? If `pkill ` return 0, then python should feedback me 0, and -1 if `pkill` return 1? – Nguyễn Louis Jan 17 '22 at 16:02
  • See my revised answer. – AKX Jan 17 '22 at 16:04
  • 1
    Summary: `pkill` *does* return 0. However, Python doesn't start `pkill`; it starts `sh` (because of `shell=True`). Normally, the `sh` process would start `pkill`, and then report the value that the `pkill` process returned. But because of how `pkill` works, *it kills the `sh` process*. So Python sees the -12 returned because that's how the `sh` process was killed. I hope this answers the first comment. – Karl Knechtel Jan 17 '22 at 16:12
  • 2
    It should also work to just *not use `-f`* for the `pkill` command, so that it only looks at the process name instead of the full command when deciding which processes to kill. After all, all the processes you want to kill have `/usr/bin/suricata` *in the process name*, right? Or do you have to kill some *other* `sh` wrappers or something? – Karl Knechtel Jan 17 '22 at 16:14
  • Thank you both so much! Finally I understand that the reason is `pkill` will kill python subprocess also. I try `pkill -SIGUSR2 /usr/bin/suricata` but pkill fail with `1`. However `pkill -SIGUSR2 -F /var/run/suricata.pid` is enough to fit me, less changes to current abstract logic <3. – Nguyễn Louis Jan 17 '22 at 16:23
  • @NguyễnLouis Ah, you should've said you have a pidfile. See my edit... – AKX Jan 17 '22 at 16:40