2009-11-05 11 views
7

Ich habe einen Prozess, den ich mit einem Shell-Skript Cygwin spawn, und ich bin nicht in der Lage, es mit dem kill Befehl zu töten. Auch bei den Cygwin kill mit der -f Option, erhalte ich diese Meldung:Konvertieren einer Cygwin-PID in eine Windows-PID

kill: couldn't open pid 1234 

Ich mag würde, um zu versuchen, es zu töten mit PsKill, aber ich kann nicht einen Weg zu konvertieren die Cygwin PID zu einem Windows PID dass PsKill verstehen finden. Wie kann ich das machen?

Antwort

10

Haben Sie versucht, den Cygwin-Kill anstelle des Bash-Builtins auszuführen? Wenn es ein Windows-PID ist dann ein:

/bin/kill -f 1234 

oder wenn es ein Cygwin PID ist dann ein:

/bin/kill -9 1234 

Soweit ich weiß, gibt es keine API Cygwin, die Sie nennen könnte übersetzen eine Cygwin PID zu einer Windows PID. Sie könnten jedoch die Ausgabe von ps -W parsen, um die Konvertierung durchzuführen. Oder, wenn Sie das wirklich nicht wirklich wollen, dann schauen Sie sich den Quellcode für den Cygwin ps Befehl an und sehen Sie, woher sie die PIDs bekommen. Der Cygwin ps source code is here.. Du könntest ein kleines Dienstprogramm in C schreiben, um die Cygwin-PID zu nehmen und dir eine Windows-PID zu geben.

+0

Ja, es ist die Cygwin-Tötung, die ich benutze. Ich habe/bin/kill -f -9 1234 und/bin/kill -9 1234 ohne Erfolg versucht. 1234 ist eine Cygwin PID. – Jazz

+2

Wenn Sie -f verwenden, dann sollten Sie es geben die Windows-PID von ps -W –

+1

Abgesehen von dieser großen Antwort - manchmal, wenn der Prozess von Windows gesperrt ist, erzeugt Cygwin kill die Meldung "konnte Pid 1234 nicht öffnen". Der Prozess muss dann zuerst aus Windows heraus entsperrt werden. – Secko

6

ps -W zeigt die Windows PID zusätzlich zur Cygwin PID.

Oder man kann es programmatisch wie folgt tun:

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

Ja, ich weiß, aber ich hatte auf einen direkten Weg gehofft, dies zu tun, anstatt die PS-Ausgabe zu analysieren. – Jazz

+0

Programmatische Alternative –

1

Dies funktioniert in sh-Shell:

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

Z_BIN enthält Ihr Programm auszuführen. Z_PID enthält cygwin pid und Z_PIDW enthält Windows pid für das gleiche Programm. Sie können Z_PIDW in einer PID-Datei speichern und später zum Töten oder für andere Zwecke verwenden.

0

Ich suchte im Internet nach, ob jemand eine Funktion oder ein Skript hatte, um Cygwin PIDs in Microsoft PIDs umzuwandeln. Ich habe keine gefunden; also habe ich mein eigenes gemacht. Ich stelle es hier zur sicheren Aufbewahrung auf (wenn ich keinen Zugriff auf meine Lebensdauer von Skripten habe, die ich programmiert habe). Dies wird eine häufige Lösung für mich in freier Wildbahn.



    #!/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} 

Verwenden Dateideskriptor, wenn Sie und anstelle dieses Rohr verwenden können.

+0

hinzugefügt Die Grammatik und der Text zum Kopieren + Einfügen wurde unten falsch interpretiert. Aber mein Stackexchange.com Jujitsu ist nicht großartig. Ich bin raus. – MyMightyJoeYoung

2

Die proc file system hat die Windows-PID für 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 
+0

Das ist in der Tat der richtige Weg! – not2qubit

0

Der beste Weg, Bash-Skripte von Cygwin zu töten läuft das Sysinternals Werkzeug PsKill64.exe verwenden. Der Grund ist, dass Cygwins ps auch PIDs gibt, die sich von WINPID unterscheiden.

Darüber hinaus hat pskill auch die -t Flag, die den gesamten Prozessbaum, der alle anderen Threads/Sub-Prozesse, die Ihr Skript möglicherweise gestartet haben, tötet. Natürlich funktioniert auch kill -9 <PID>, aber Nachkommen, die bereits vom Skript gestartet wurden, werden nicht gelöscht.

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

Jetzt laufen mit:

$ ./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 

Wie Sie sehen, diese beiden Prozesse beginnt, die Haupt bash Skript und den Schlaf-Thread. Also, wenn Sie kill -1 8132 der Schlaf-Thread wird weiterhin ausgeführt werden, aber wenn Sie pskill64 -t 8132 verwenden, werden Sie auch alle seine Nachkommen töten. Analog zum Linux Befehl.

Verwandte Themen