Isso é complicado. Primeiro, apenas por precaução, coloque a chamada em uma função no início do script e não a chame até o final:
% killmenow() { ... }
...
% killmenow
EOF
Esta é a melhor maneira de ter certeza de que tudo a partir do script atual foi totalmente lido e copiado para a memória. Apenas dizendo.
Agora, para minha tentativa de resposta ...
POSIX especifica os utilitários jobs
para esses tipos de coisas. Especificamente, uma combinação de wait
, trap
e kill
seria mais segura, eu acho. Para que as coisas estejam se movendo da maneira mais limpa possível, você também pode usar newgrp
, que é muito parecido com exec
em qualidades de herança, exceto, como poderia ser fundamental neste caso, process id
.
Ok, então sei que parece muito, mas depois de tudo não é para olhar:
% suicide() { _me="${1}" ; (
>> trap 'wait "${_me}" && set -- &&\
>>> eval 'newgrp && exec { YOUR | CMD | HERE }'' INT &&\
>> kill -s INT "-${_me}"
>> ) & }
...
% suicide "${$}"
Ok, então aqui está o fluxo de trabalho:
- First we load and run the entire script and we're sure of this because we don't
suicide
until the very last line.
- We pass to
suicide
a copy of our process id
then save it to $_me
, which we could just as easily get from within suicide
as well in this case, but we might use it elsewhere, who knows.
- From within a subshell we call
trap
to scan in its trapped
'$cmd'
and instruct it to be on the lookout for any rumor of an INT
call.
- Sure all is ready, our call to
kill
is our very last; kill
issues an INTERRUPT SIGNAL
not only to $_me
but we -
specify that $_my
process whole group should receive it. Have no fear - unless your whole system is already insane - $_me
can't kill anything $_me
shouldnt be able to right now anyway. Also, you dont have to -
specify that in kill
's PID
argument either; I'm just trying to be thorough.
Ok, mas não terminamos, certo? Não, colocamos todo o conjunto de comandos em uma subshell &
backgrounded, então trap
ainda está por perto e podemos capturar nossa chamada INT
.
- Having recieved its
INT
, trap
NOW evaluates its 'quoted argument'
- it's important to remember that anything within this string is only now being pulled out.
- Just in case
$_me
has a few other loose ends to tie up elsewhere, trap
first calls wait
on $_me
which will hold the line only for as long as it must.
- When ready, we scrub any remaining
env $vars
with set --
and then we get down to business.
newgrp
foi projetado para ser executado em interactive shell
- não é necessariamente necessário fornecer um processo tão limpo como este. Na verdade, se o group
do seu sistema exigir senhas - o que elas não deveriam - isso não funcionará para você e morrerá agora.
Eu chamo esse método sorrateiro abaixo, mas eu o retirei diretamente das orientações do POSIX:
A common implementation of newgrp
is that the current shell uses exec
to overlay itself with newgrp
, which in turn overlays itself with a new shell after changing group...
Então, no próximo parágrafo ...
The newgrp command is intended only for use from an interactive terminal. It does not offer a useful interface for the support of applications.
Assim, a parte sorrateira é eval
, o que pode ser muito bom nesse tipo de coisa - como salvar e reutilizar "$@"
, por exemplo, mas em outra ocasião, talvez ...
- Instead, we indirectly
eval
a newgrp && exec
statement that first loads another process that is only supposed to take its next command from an interactive prompt, then we sneakily exec
in the back door the contents of { YOUR | CMD }
.
A essa altura, deveríamos estar executando um novo script em um novo shell em um novo grupo de processos em um ambiente limpo, depois de ter que esperar apenas o tempo que fosse necessário e ter retirado a coisa toda bem.
Na verdade, éramos tão meticulosos que poderíamos fazer isso com segurança:
...exec { wget -O - "${URL}" >"${0}" ; exec "${0}" }