Qual system() do awk deve retornar está mal especificado .
O que parece ser comum entre awk implementações é que, após uma saída normal, ele retorna o código de saída (o número passou para exit(3) módulo 256), mas quando o processo shell é morto por um sinal, há um muito comportamento diferente.
Observe também que, embora a função C system(3) deva ignorar SIGINT (e SIGQUIT) no pai, não está muito claro (pelo menos para mim) que o requisito também se aplica a awk ' system() . Algumas awk implementações (como mawk ) morrerão naquele SIGINT (esse também é o comportamento que eu gostaria de ver, pois não gosto de meu CTRL-C ser ignorado apenas porque awk está rodando o system() function), algumas (como gawk ou implementações tradicionais) não.
Observe também que alguns shells podem interceptar alguns desses sinais e eventualmente chamar exit() , o que afetaria o comportamento (veja a discussão em comentários sobre o shell Bourne, por exemplo), é por isso que uso exec nos exemplos abaixo para remover o shell do loop.
Para o valor retornado por system() (há ainda mais variação se você considerar close() 1 ) em um SIGINT, vemos:
$ nawk 'BEGIN {print system("exec kill -s INT $$")}'
0.0078125
$ bwk-awk 'BEGIN {print system("exec kill -s INT $$")}'
0.0078125
$ mawk 'BEGIN {print system("exec kill -s INT $$")}'
130
$ gawk 'BEGIN {print system("exec kill -s INT $$")}'
0
0.0078125 sendo 2 / 256 (para SEGV de 11 , você obteria 0,542969 ((128 + 11) / 256) se um núcleo fosse descartado, 0,0429688 (11/256) caso contrário), nawk sendo o nawk encontrado no Solaris 10 ou 11, ou sua porta Linux no toolchest da Heirloom, bwk-awk sendo o awk mantido pelo próprio Brian Kernighan (o K em awk ) a base para o awk encontrado em alguns BSDs (aqui testados no Debian GNU / Linux). /usr/xpg4/bin/awk no Solaris 11 se comporta como gawk .
Portanto, com base no valor s retornado por system(3) (um inteiro onde os bits 0 a 6 são o número do sinal, o bit 7 o core-bit e os bits 8 a 15 o código de saída), awk ' s system() acima retorna:
-
s / 256(tradicionalawkimplementations), -
int(s/256)(gawk), - ou em
mawk, a mesma transformação feita por shells como Bourne ou C-shell, por exemplo ((s&127)+128se morto,s>>8caso contrário), exceto que se um núcleo for descartado, você obtém(s&127)+256em vez de(s&127)+128(o valor é(s&255)+128).
Então, aqui, você poderia fazer:
awk 'BEGIN{print system("trap exit\ 1 INT; sleep 10")}'
Mas isso ainda faria com que awk fosse eliminado com algumas implementações awk , como mawk . Se o seu sh for bash ou yash , você poderá fazer:
awk 'BEGIN{print system("set -m; sleep 10; exit")}'
Portanto, sleep é executado em seu próprio grupo de processos (e apenas obtém o SIGINT).
Outra alternativa poderia ser ignorar o SIGINT antes de chamar awk . No entanto, a maioria das shells (e isso é um requisito POSIX) não pode mudar um manipulador de sinal se o sinal já foi ignorado no início. Então coisas como:
(
trap '' INT
awk 'BEGIN{print system("trap exit\ 1 INT; sleep 10; exit")}'
)
não vai funcionar. zsh não tem essa limitação (auto-infligida), então se você sabe que zsh está disponível, você poderia fazer:
(
trap '' INT
awk 'BEGIN{print system("exec zsh -c \"TRAPINT() exit 1; sleep 10\"")}'
)
O que funcionaria se awk fosse mawk , gawk ou outro e evitaria ter que mexer no controle do trabalho. Neste ponto, vale a pena considerar usar perl / python / ruby ... em vez de awk , onde você pode adaptar o tratamento de sinais às suas necessidades.
Notas
1 Sobre close() de um pipeline, como em:
awk 'BEGIN {cmd = "kill -s INT $$"; cmd | getline; print close(cmd)}'
Primeiro, desta vez ^C interrompe awk em todas as implementações que eu tentei (não existe esse requisito para ignorar o SIGINT / SIGQUIT para popen(3) / pclose(3) (uma maneira natural de implementar esse getline ) como existe para system(3) ).
Mas, quando se trata do status de saída (em que s é o valor retornado por pclose(3) / waitpid(2) , como para system() acima), vemos:
- O Solaris
nawk: não funciona, você não pode chamarclose()assim no Solarisnawk. -
/usr/xpg4/bin/awkno Solaris. Retorna sempre 0, mesmo após umexit(1)feito pelo processo. Claramente um bug de conformidade. -
gawkebwk-awk: dás(exit 1fornece 256, morto por SIGINT, 2, morto por um SIGSEGV de 11 com núcleo, dá 139). -
mawk: o mesmo que parasystem(), parece quemawké a única implementação que pensou nisso.