Converta um pid de cygwin em um pid de janelas
-
16-09-2019 - |
Pergunta
Eu tenho um processo que desonesto com um Cygwin script de shell, e não consigo matá -lo com o kill
comando. Mesmo com o Cygwin Kill com o -f
opção, recebo esta mensagem:
kill: couldn't open pid 1234
Eu gostaria de tentar matá -lo com Pskill, mas não consigo encontrar uma maneira de converter o Cygwin PID
para um Windows PID
este PsKill
vai entender. Como eu posso fazer isso?
Solução
Você já tentou executar a matança de Cygwin em vez da festa embutida? Se for um PID do Windows, digite:
/bin/kill -f 1234
ou se for um cygwin pid, digite:
/bin/kill -9 1234
Até onde eu sei, não há API para o Cygwin que você poderia ligar para traduzir um PID de Cygwin em um PID do Windows. No entanto, você pode analisar a saída de ps -W
Para fazer a conversão. Ou, se você realmente, realmente não quer fazer isso, dê uma olhada no código -fonte do Cygwin ps
comando e veja de onde eles tiram os PIDs. O cygwin O código -fonte do PS está aqui.. Você pode escrever um pequeno utilitário em C para pegar o PID do Cygwin e fornecer um PID do Windows.
Outras dicas
ps -W
mostrará o PID do Windows, além do Cygwin PID.
Ou, você pode fazer isso programaticamente assim:
#include <sys/cygwin.h>
winpid = cygwin_internal(CW_CYGWIN_PID_TO_WINPID, cygpid);
o Sistema de arquivos proc tem o pid Windows para cygwin pid $ pid em /proc/$pid/winpid
.
> notepad&
[1] 11716
> taskkill /f /pid $(</proc/$!/winpid)
ERFOLGREICH: Der Prozess mit PID 11976 wurde beendet.
[1]+ Exit 1 notepad
Isso funciona em sh shell:
./${Z_BIN} &
Z_PID=$!
Z_PIDW=`ps -p ${Z_PID} | awk -e '/^[[:space:]]+[[:digit:]+]/{print $4}'`
Z_BIN contém seu programa para executar. O Z_PID conterá o Cygwin PID e o Z_PIDW conterá o Windows PID para o mesmo programa. Você pode salvar o Z_PIDW em um arquivo PID e usá -lo posteriormente para matar ou qualquer outro propósito.
Eu procurei na web para ver se alguém tinha uma função ou script para converter PIDs de cygwin em PIDs da Microsoft. Eu não encontrei nenhum; Então eu fiz o meu próprio. Estou colocando isso aqui para manutenção segura (quando não tenho acesso à minha vida em scripts que programei). Isso está se tornando uma solução frequente para mim na natureza.
#!/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 o descritor de arquivo quando puder e usar em vez desse tubo.
A melhor maneira de matar scripts bash em execução de Cygwin é usar o Sysinternals ferramenta PsKill64.exe
. A razão é que o cygwin ps
Dê também PIDs que são diferentes de WINPID
.
Além disso, pskill
também tem o -t
Bandeira que mata toda a árvore do processo, o que significa quaisquer outros threads/subprocessos que seu script possa ter iniciado. É claro kill -9 <PID>
Também funciona, mas não mata descendentes já iniciados pelo roteiro.
# cat sleeper.sh
ZID=$$
WINPID=$(cat /proc/${ZID}/winpid)
echo "WINPID: ${WINPID}"
sleep 10
Agora corra com:
$ ./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
Como você vê, isso inicia dois processos, o principal bash
Script e o fio do sono. Então, se você kill -1 8132
O tópico do sono continuará correndo, mas se você usar pskill64 -t 8132
, você matará todos os seus descendentes também. Análogo ao Linux killall
comando.