Convert a Cygwin PID to a Windows PID
Asked Answered
A

6

7

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?

Antibes answered 5/11, 2009 at 9:24 Comment(0)
L
9

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.

Legal answered 5/11, 2009 at 9:31 Comment(4)
Yes, it is the Cygwin kill I'm using. I tried /bin/kill -f -9 1234 and /bin/kill -9 1234 with no success. 1234 is a Cygwin PID.Antibes
If you use -f, then you should give it the Windows PID from ps -WLegal
Apart from this great answer - sometimes when the process is locked from inside Windows, Cygwin kill spawns the "couldn't open pid 1234" message. The process then needs to be unlocked from inside Windows first.Leann
Thank you for this distinction! I was going crazy trying to figure out why "kill -f <pid>" wasn't working for a windows pid. That's going into the "never forget this!" file for Cygwin commands. :)Sarcasm
V
9

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);
Virgulate answered 5/11, 2009 at 9:32 Comment(0)
F
8

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
Flora answered 1/7, 2017 at 15:45 Comment(0)
L
2

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.

Lover answered 4/11, 2017 at 18:57 Comment(0)
K
1

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.

Kirimia answered 17/11, 2013 at 2:38 Comment(0)
N
0

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.

Neukam answered 7/9, 2016 at 19:24 Comment(1)
The grammar and copy+paste text got mis-interpreted at the bottom there. But my stackexhange.com jujitsu is not great. I'm out.Neukam

© 2022 - 2024 — McMap. All rights reserved.