Trap 'Ctrl + c' para o script bash, mas não para o processo aberto neste script

11

Tentei ter um programa interativo em um script bash:

my_program

E eu gostaria de poder fechá-lo com 'Ctrl + c'. Mas quando eu faço isso, meu script também está fechando.

Eu sei sobre.

trap '' 2
my_program
trap 2

Mas, neste caso, simplesmente não consigo fechar my_programcom Ctrl + c.

Você tem alguma idéia de como permitir Ctrl + c em um programa, mas não fecha o script que o executa?

EDIT: add example

#!/bin/bash
my_program
my_program2

Se eu usar Ctrl + c para fechar my_program, my_program2nunca será executado porque todo o script foi encerrado.

bob dylan
fonte

Respostas:

13

Você deve usar trap true 2ou em trap : 2vez de trap '' 2. Isso é o que "ajuda a interceptar" em um shell bash diz sobre isso:

Se ARG for a sequência nula, cada SIGNAL_SPEC será ignorado pelo shell e pelos comandos que ele chama .

Exemplo:

$ cat /tmp/test
#! /bin/sh
trap : INT
cat
echo first cat killed
cat
echo second cat killed
echo done
$ /tmp/test
   <press control-C>
^Cfirst cat killed
   <press control-C>
^Csecond cat killed
done
mosvy
fonte
2
Que tal matar tails em vez de matar gatos na próxima vez?
Kubanczyk
12

Você pode redefinir uma armadilha para o padrão, fornecendo o comando trap -como seu argumento de ação. Se você fizer isso em um subshell , isso não afetará a armadilha no shell pai. No seu script, você pode fazer isso para cada comando que precisa ser interrompido com Ctrl-C:

#!/bin/bash
# make the shell (and its children) ignore SIGINT
trap '' INT
.
.
.
# but this child won't ignore SIGINT
(trap - INT; my_program)
# the rest of the script is still ignoring SIGINT
.
.
.
Mark Plotnick
fonte
1
Embora a resposta aceita seja provavelmente melhor e mais canônica para o shell, esta é uma ótima resposta em si, pois introduz o princípio geral (não específico do shell) de como fazer esse tipo de sinal mascarando / ignorando com segurança.
R .. GitHub Pare de ajudar o gelo
Eu acho que você pode exec my_programno subshell, para ser um pouco mais eficiente.
precisa saber é o seguinte
@R .. isso absolutamente não é específico do shell - se você definir um sinal para SIG_IGN (é o que a armadilha com uma string vazia está fazendo), esse estado será herdado por meio de exec (), exceto SIGCHLD. Esse é o comportamento obrigatório do POSIX. Veja também a resposta para stackoverflow.com/questions/32708086/…
mosvy
@mosvy: Não vejo com que parte do meu comentário você está discordando. Meu argumento principal era que "mascarar / ignorar antes da bifurcação, desmascarar / não ignorar na criança antes da execução" é um princípio geral que é útil conhecer fora do contexto da programação de shell.
R .. GitHub Pare de ajudar o gelo
1
Esta é uma resposta muito útil. Como um usuário experiente do Linux, posso dizer que nunca ouvi falar disso antes. Tem muitos usos ... você recebeu meu voto positivo e meu favorito.
Dev
-1


Quando você usa Crtl+ C, você interrompe o programa (" mata ").
O que você provavelmente está procurando é suspender seu programa (" pausar "). Para isso, você pode usar Crtl+ Z.
Depois que o programa estiver em pausa, você poderá vê-lo usando jobs. Por exemplo:
[1]+ Stopped ./foobar
Aqui eu tenho apenas um emprego, trabalho nº 1, mas pode haver mais de um - cada trabalho tem seu próprio número.
Você pode controlar o processo suspenso usando vários comandos, por exemplo bg, fge kill.
bg %1reiniciará trabalho # 1 no b ack g rodada
fg %1reinício do trabalho # 1 no f minériog round
kill %1matará o trabalho nº 1
Observe que você pode usar bge fgsem argumentos se tiver apenas um trabalho ativo.

pi0tr
fonte
Obrigado, mas não, desejo fazer Ctrl + c.
quer