Saia do terminal após executar um script bash

18

Estou tentando escrever um bashscript para abrir determinados arquivos (principalmente arquivos PDF) usando o gnome-opencomando Também quero que o terminal saia assim que abrir o arquivo pdf.

Eu tentei adicionar exitno final do meu script, no entanto, isso não fecha o terminal. Eu tentei procurar online uma resposta para minha pergunta, mas não consegui encontrar uma adequada, eu realmente apreciaria se vocês pudessem ajudar.

Preciso de uma resposta que mate apenas o terminal a partir do qual executo o comando. Nem todos os terminais seriam possíveis? A resposta anterior, que aceitei, mata todas as janelas do terminal que estão abertas. Eu não sabia que era esse o caso até hoje.

Rumesh
fonte
Você está executando o script no terminal em primeiro lugar? Estritamente na linha de comando, não há razão para abrir o terminal para fazer isso.
precisa saber é o seguinte
Sim, eu executo o script do terminal. Eu não perceber que havia uma diferença entre a linha terminal e comando
Rumesh
Substituí o gnome-openpor xdg-openno meu script, mas não há alterações. O ainda o terminal permanece aberto
Rumesh
@ Tim Wow, funciona =) +1
AB
@ Tim Mas minha solução também não era ruim. ;)
AB

Respostas:

12

Se você estiver abrindo apenas um arquivo, não precisará realmente usar um script, porque um script deve ser uma maneira fácil de executar vários comandos em uma linha, enquanto aqui você só precisa executar dois comandos (incluindo exit) .

Se você deseja executar exitapós um comando ou após uma cadeia de comandos, pode encadeá-lo ao que já possui usando o &&operador (que, com sucesso do comando / cadeia de comandos anterior, executará o próximo comando) ou usando o comando ;operador (que, com êxito e com falha do comando / cadeia de comandos anterior, executará o próximo comando).

Nesse caso, seria algo assim:

gnome-open <path_to_pdf_file> && exit

* <path_to_pfd_file> = caminho do arquivo pdf

exitcolocar no final de um script não funciona porque sai da bashinstância em que o script é executado, que é outra bashinstância que não a bashinstância interna do Terminal .

Se você deseja usar um script de qualquer maneira, a maneira mais direta é chamar o script da seguinte maneira:

<path_to_script> && exit

Ou se o script estiver no diretório de trabalho atual do Terminal, da seguinte maneira:

./<script> && exit

Se você realmente não quer / não pode fazer isso, a segunda maneira mais direta é adicionar esta linha no final do seu script:

kill -9 $PPID

Isso enviará um SIGKILLsinal para o processo pai do script (a bashinstância vinculada ao Terminal). Se apenas uma bashinstância estiver vinculada ao Terminal, essa interrupção fará com que o Terminal se feche. Se várias bashinstâncias estiverem vinculadas ao Terminal, a eliminação não fará com que o Terminal se feche.

kos
fonte
2
O sinal SIGTERM é enviado a um processo para solicitar seu término. Ao contrário do sinal SIGKILL, ele pode ser capturado e interpretado ou ignorado pelo processo. Isso permite que o processo execute uma finalização agradável, liberando recursos e salvando o estado, se apropriado. SIGINT é quase idêntico ao SIGTERM.
AB
@AB Você está certo, SIGTERMaqui não é suficiente.
kos
Obrigado pela resposta. Eu acho que eu só vou usar o único comando que você deu na sua resposta
Rumesh
kill $ PPID faz o mesmo que sair - nada. E kill -9 $ PPID fecha todas as janelas filho junto com o pai.
SDsolar
5

Este script finaliza o terminal e, portanto, o shell e ele próprio.

Sem piedade, mata todos os processos. Se você tiver várias guias abertas em um terminal, elas também serão fechadas.

O problema é que, se vários terminais forem abertos e esses forem processos filhos gnome-terminal-server, todos os terminais serão eliminados.

Nesse caso, o script deve ser iniciado em um terminal independente, por exemplo xterm

<your_command> & disown

PPPID=$(awk '{print $4}' "/proc/$PPID/stat")
kill $PPPID
  • PPID

    O PPID é o ID do processo pai, neste caso o shell ( e.g. /bin/bash)

  • PPPID

    O PPPID é o ID do processo pai do PPID, nesse caso, a janela do terminal

  • <your_command> & disown

    No shell bash, o comando disown builtin é usado para remover trabalhos da tabela de trabalhos ou para marcar trabalhos para que um sinal SIGHUP não seja enviado a eles se o shell pai o receber (por exemplo, se o usuário fizer logout).

  • awk '{print $4}' "/proc/$PPID/stat"

    Obtém o valor da quarta coluna do arquivo /proc/$PPID/stat(por exemplo /proc/1/stat, retorna 0)

AB
fonte
Eu acho que o comando $$ get é o pid do terminal ... Isso seria uma alternativa? Você também pode explicar como negar?
Tim
Como esse script faz isso? Ainda sou novo no shell script, por isso não consigo realmente entender esses comandos. Poderia explicar como ele fecha o terminal
Rumesh
11
@ Tim Não, ele retorna o shell em um terminal: ps xa | grep $$=> 4381 pts/0 Ss 0:01 /usr/bin/zsh
AB
11
@RumeshSudhaharan Mata toda a janela do terminal na qual o script é iniciado, mas nenhuma outra janela do terminal.
AB
3
@AB você disse anteriormente que isso apenas mata a janela atual do terminal e não nenhuma outra. Eu usei esse script hoje com duas janelas de terminal abertas e as duas foram mortas depois que eu executei o script.
Rumesh
4

Você pode usar .exec ./your-script

Um emulador de terminal como o GNOME Terminal é encerrado quando o processo inicial em execução nele - que geralmente é um shell - termina.

Se você já está em um terminal e a única coisa que deseja fazer antes de sair desse terminal é executar um script (ou programa) específico, isso significa que você não precisa mais do shell que está sendo executado nele. Assim, você pode usar o execbuiltin do shell para fazer com que o shell se substitua pelo processo criado por seu comando.

  • No caso do seu script, esse é outro processo de shell - assim como um segundo processo de shell é criado quando você executa um script sem exec.

A sintaxe é , por exemplo ,.exec commandexec ./your-script

exec: um exemplo

Por exemplo, suponha que eu tenha um script de shell chamado count, marcado como executável e localizado no diretório atual. Contém:

#!/usr/bin/env bash
for i in {5..1}; do echo $i; sleep 1; done

E, em um terminal, eu corro:

exec ./count

Isto imprime o numerais 5, 4, 3, 2, e 1, por um segundo, e em seguida, os terminais fecha a janela.

Se você executar isso a partir de algo diferente do primeiro processo executado no seu terminal - por exemplo, se você executou bashprimeiro para iniciar outra instância do shell - isso o levará de volta ao shell que criou esse processo, em vez de sair do terminal. (Esta ressalva se aplica igualmente a exitmétodos baseados em).

Você pode usar ../your-script; exit

Se você não quiser dizer ao seu shell para substituir-se pelo novo processo (via exec), você pode pedir para ele permanecer, mas sair imediatamente após o término do novo processo.

Para fazer isso, execute seu comando e o exitcomando, separados por, ;para que possam ser fornecidos em uma linha.

A sintaxe é command; exit, por exemplo ,../your-script; exit

command; exit vs. command && exit

Você pode notar que isso se parece com o método sugerido nas respostas de kos e heemayl . A diferença é que:./your-script && exit

  • &&executa o segundo comando somente se o primeiro comando relatou que obteve êxito retornando um código de saída zero.
  • ; executa o segundo comando, independentemente de o primeiro comando ter relatado ou não sucesso.

Qual você deseja depende da situação específica. Se o comando falhar, você deseja que o shell de chamada (e o terminal de hospedagem) permaneça ativo? Se sim, use &&; caso contrário, use ;.

Também existe command || exit, que fecha o shell de chamada apenas se houver falhacommand relatada .

Eliah Kagan
fonte
2

Você pode fonte seu script em vez de executá-lo, por exemplo

$ cat run.sh
exit;
$ ./run.sh #will not close
$ . ./run.sh # will close
RiaD
fonte
1

Pessoalmente, eu executaria o comando para abrir pdf ou outros arquivos em subshell, colocaria um atraso para permitir a abertura dos arquivos e depois sairia. Basicamente, aqui está o que eu testei(nohup gnome-open *.pdf &); sleep 2; exit

Variação sobre isso seria nohup gnome-open *.pdf && sleep 2 && exit

Sergiy Kolodyazhnyy
fonte
No meu caso, já que nohupignora o sinal de desligamento, nohup xdg-open some_programfuncionou para mim e exitfoi desnecessário. nohupredireciona a mensagem para um nohup.outarquivo:nohup: ignoring input and appending output to nohup.out
nick indiessance
0

A solução mais simples seria:

xdg-open file.pdf && exit

Ao contrário de outro comando semelhante, nohupnão é necessário para fazer com que o comando seja ignorado SIGHUP, o motivo xdg-openserá que você gerará um processo filho, que é o aplicativo preferido para abrir o arquivo pdf. Como o processo real iniciado no terminal não está mais lá para ser morto, nohupnão é necessário.

&&indica que o próximo comando será executado se o comando anterior for bem-sucedido, ou seja, retorna o código de saída 0( $?=0) e exitsimplesmente fecha o terminal.

heemail
fonte
Acho que ele disse saída não estava funcionando ...
Tim
@ Tim: Talvez OP não usá-lo da maneira certa, a partir da pergunta é muito claro para mim como é que ele / ela colocou exitno final e não funcionou ..
heemayl
11
@ Tim Porque o OP colocou exitdentro do script, o que é inútil, pois tem o efeito de sair da bashinstância em que o script está sendo executado, e não da bashinstância pai (aquela vinculada ao Terminal), que faria com que o Terminal fosse fechado
kos
11
De qualquer forma, xdg-openjá é executado em segundo plano e desvinculado do Terminal, portanto, você não precisa nohupaqui, além do que eu entendo, o OP é executado xdg-openvárias vezes dentro de um script para abrir vários arquivos em lote, usando xdg-openassim dentro do script causaria o script sair na primeira xdg-openocorrência
kos
@ kos: Não, eu não estou executando xdg-openno backgr, mesmo que eu tivesse nohuppor um motivo diferente e deve estar lá .. qualquer processo em segundo plano do terminal de origem será morto quando você matar o terminal pai .. nohupexiste para impedir it..como não preciso usar o terminal interativamente novamente, não há necessidade de colocar o processo em bg .. no seu segundo ponto que também pode ser evitado executando cada xdg-open && exitum em uma subshell ..
heemayl
0

Para responder explicitamente à pergunta do título,

"Saia do terminal depois de executar um script bash" :

Execute apenas seu script no terminal

Sem examinar os detalhes do que o script faz, um script pode ser executado diretamente dentro de um terminal com a opção -e( --command), sem iniciar um shell - ele é usado no lugar do shell e:

gnome-terminal -e ./script.sh

Use a opção -x( --execute) quando desejar fornecer argumentos para o script. Com isso, apenas todo o restante da linha de comando é tomado como comando e argumentos.

gnome-terminal -x ./script.sh foo bar

Se o seu script sair, não haverá um shell interativo que aguente qualquer coisa, aguardando a entrada do usuário.

Exemplos

O teminal sairá após o comando em execução sair - assim, o fechamento após a sleepexecução de 4 segundos, sem shell:

gnome-terminal -x sleep 4

Obviamente, você ainda pode usar scripts de shell, porque seu script está usando uma instância de shell diferente de qualquer maneira.

Além disso, você pode executar um shell com um script explícito - ele não será interativo:

gnome-terminal -x bash -c "echo 'Hello!'; sleep 4"
Volker Siegel
fonte