5

After running the following commands (bash) as root via SSH:

    pkill --help
    pkill -h
    pkill /?

The first two commands didn't provide me any information, that's why ran the third (kinda instinctively...).

What happened next is that my SSH session to the server closed, and it wouldn't reconnect. I'm guessing that it stopped all (or most of) the running processes, including the daemon in-charge for such sessions.

I would like to understand why this happened: What is the exact evaluation (step-by-step) of my input and what did it cause.

My best guess is that it has something to do with the shell's evaluation of the '?' character, which probably translated to a list of a few single-character expressions which were passed on to pkill, which in turn closed these PID's.

scooz
  • 233
  • 1
  • 3
  • 8
  • 4
    The command you were looking for was `man pkill`. :) – Sven Jul 12 '12 at 14:27
  • 1
    Just wanted the basic usage, not the "entire man page", so it was kind of an instinct. However, when you play with fire, you just might get burned :) – scooz Jul 12 '12 at 14:36
  • 2
    @scooz As a general rule, unix commands _almost never_ accept `/?` as a help command. Typically this also applies separately - they almost never use `/` for switches (`-` or `--` are more common), nor accept `-?` for help [though there are a few that do that IIRC] – Random832 Jul 12 '12 at 18:07

3 Answers3

20

On CentOS 5.2, the man page provided by running man pkill says it would interpret the /? as an extended regular expression for process names or command lines.

So the ? means the previous caracter may or may not appear. Since there was only one other character, the /, then pkill killed every process it could.

On linux systems, try to remember the man command to get documentation first.

becomingwisest
  • 3,328
  • 20
  • 18
  • So '/?' evaluates to either '/' or ''. Why does this result in killing every process possible? – scooz Jul 12 '12 at 14:34
  • 1
    The '/?' evaluated to / (see http://www.regular-expressions.info/reference.html). Try running `ps awux | egrep /` and see what it matches. Almost everything. `pkill` pretty much does the same match, takes the PIDs and kills them. – ablackhat Jul 12 '12 at 15:01
  • 11
    @ablackhat Actually, it will match everything, since the "/" is optional in the process name. You can use any other character followed by a "?" and get the same result: your matching logic will basically be "process name has character A or it doesn't have A", which is always true. Run `pgrep -l /?` to see the names also; you'll find that these don't have "/" in the name. `pgrep` doesn't match on the same things that your `ps auxw | egrep /` will, as `ps auxw` will show executable paths, which will have "/" in them. – cjc Jul 12 '12 at 15:08
  • So it's because the `pgrep` or `pkill` pattern parameter also matches the process names or command lines (as mentioned in the man page). Since most commands include the `/` character (include paths), processes are matched almost all the time. Thanks – scooz Jul 12 '12 at 15:13
  • 2
    @scooz, No, most of the process names don't include "/" at all. As said, run `pgrep -l /?` to see this. Or, for that matter, `pgrep -l a?`. You'll see that it'll match sshd, which obviously doesn't have an "a" in it, much less "/". It's more the logic of the regex: the name is required to "have that character or not have that character", i.e., the conditional will always return true. Actually, more in terms of how the regex docs are written: the name will have 0 or 1 "/" characters in it, as specified by the "?" modifier. – cjc Jul 12 '12 at 15:16
  • Actually, shouldn't "pgrep /?" return "pgrep: No match." because the shell interprets '?' before pgrep can? –  Jul 12 '12 at 16:28
  • @barrycarter, It did something like that when I tried `pgrep /*` (the shell evaluated multiple files under directory `/` and sent them as arguments to pgrep), but not with `/?`. I think its because the shell doesn't find any results for the `/?` evaluation, so it leaves it as is, and it is passed on to pgrep. – scooz Jul 12 '12 at 17:01
  • @scooz Hmmm, your shell settings might be different than mine. I actually ran the command and got "pgrep: No match". I think my shell settings (I'm using tcsh, BTW) abort a command when there's no match? When I do "pgrep /*" it gives me back a usage message, since pgrep accepts only one argument... –  Jul 12 '12 at 17:25
  • 1
    You want to be very careful in a script that a variable argument is not empty: `pkill "$emptyvar"` – Dennis Williamson Jul 13 '12 at 01:58
7

Run pgrep /?...

That will return the PIDs of processes matching that shell pattern. Running pkill with the same parameter will kill everything listed in the pgrep /? output.

I think you were killing your own session, as well as a number of other processes (all PIDs, in this case).

ewwhite
  • 197,159
  • 92
  • 443
  • 809
  • I'll remember to pgrep something in the future before running pkill :). However, see my comment to becomingwisest's answer - why does it evaluate to all the processes? – scooz Jul 12 '12 at 14:40
  • It does, at least on my system. You just can't kill everything, and `pkill` won't be able to kill anything after it kills itself. – BillThor Jul 13 '12 at 01:06
3

The syntax of command line expressions of /switch1 /switch2 is a Windows/DOS thing. On Linux, and all UNIXes I know off, the command line argument syntax is --switch -s. /? is being thought of as a regular expression. The regular expression /?, at least as far as I can tell from grep's man page, would match 0 or 1 /es. That doesn't seem to explain why that would kill SSH, but it does explain what happened.

Linuxios
  • 133
  • 7