Question

I have a process I spawn with a Cygwin shell script, and I am unable to kill it with the kill command. Even with the Cygwin kill with the -f option, I get this message:

kill: couldn't open pid 1234

I would like to try to kill it with PsKill, but I cannot find a way to convert the Cygwin PID to a Windows PID that PsKill will understand. How can I do that?

Was it helpful?

Solution

Have you tried running the cygwin kill instead of the bash builtin? If it is a Windows PID then type:

/bin/kill -f 1234

or if it is a Cygwin PID then type:

/bin/kill -9 1234

As far as I know there is no API to Cygwin that you could call to translate a Cygwin PID to a Windows PID. However, you could parse the output of ps -W to do the conversion. Or, if you really, really don't want to do that, then have a look at the source code for the Cygwin ps command, and see where they get the pids from. The Cygwin ps source code is here.. You could write a small utility in C to take the Cygwin pid and give you a Windows pid.

OTHER TIPS

ps -W will show the Windows PID in addition to the Cygwin PID.

Or, you can do it programmatically like this:

#include <sys/cygwin.h>
winpid = cygwin_internal(CW_CYGWIN_PID_TO_WINPID, cygpid);

The proc file system has the windows PID for cygwin PID $pid in /proc/$pid/winpid.

> notepad&
[1] 11716
> taskkill /f /pid $(</proc/$!/winpid)
ERFOLGREICH: Der Prozess mit PID 11976 wurde beendet.
[1]+  Exit 1                  notepad

This works in sh shell:

./${Z_BIN} &
Z_PID=$!
Z_PIDW=`ps -p ${Z_PID} | awk -e '/^[[:space:]]+[[:digit:]+]/{print $4}'`

Z_BIN contains your program to execute. Z_PID will contain cygwin pid and Z_PIDW will contain windows pid for the same program. You can save Z_PIDW in to a pid file and use it later for killing or any other purpose.

I searched the web to see if anyone had a function or script to convert cygwin PIDs to Microsoft PIDs. I found none; so I made my own. I am putting it up here for safe keeping (when I do not have access to my life-time of scripts that I have programmed). This is becoming a frequent solution for me out in the wild.



    #!/usr/bin/env bash
    # Convert a cygwin PID to a Microsoft PID using bash and perl
    ps -W | perl -e '
    my ($line, $arg,$errno,@columns);
    $errno=1;
    while($line = ){
      chomp($line);
      $line=~s/^\s+//g;s/\s+$//g;
      for $arg (@ARGV){
        if ($line=~/^${arg}/){
          $errno=0;
          @columns=split(/\s+/,$line);
          print STDOUT $columns[3];
          last;
        }
      }
    }
    exit($errno);
    ' "${@}"
    
The kill using `taskkill` and/or `kill` cygwin terminal.
<pre><code>
taskkill /F /IM ${m1crosoft_pid_goes_here}
kill -9 ${cygwin_pid_goes_here_tmp}

Use file descriptor when you can and use instead of that pipe.

The best way to kill running Bash scripts from Cygwin is using the Sysinternals tool PsKill64.exe. The reason is that Cygwin's ps also give PID's that are different from WINPID.

In addition, pskill also has the -t flag that kills the entire process tree, which means any other threads/sub-processes that your script may have started. Of course kill -9 <PID> also works, but it doesn't kill descendants already started by the script.

# cat sleeper.sh
ZID=$$
WINPID=$(cat /proc/${ZID}/winpid)
echo "WINPID: ${WINPID}"
sleep 10

Now run with:

$ ./sleeper.sh &
[1] 8132
WINPID: 8132

$ ps
      PID    PPID    PGID     WINPID   TTY         UID    STIME COMMAND
     #5280       1    5280       5280  ?           1001 14:21:40 /usr/bin/mintty
     #7496    5684    7496       3836  pty0        1001 20:48:12 /usr/bin/ps
     #5684    5280    5684       6052  pty0        1001 14:21:40 /usr/bin/bash
     5948    8132    8132       3900  pty0        1001 20:48:11 /usr/bin/sleep
     8132    5684    8132       8132  pty0        1001 20:48:11 /usr/bin/bash

As you see, this starts two processes, the main bash script and the sleep thread. So if you kill -1 8132 the sleep thread will continue running, but if you use pskill64 -t 8132, you will kill all its descendants too. Analogous to the linux killall command.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top