AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 778251
Accepted
intelfx
intelfx
Asked: 2024-06-13 09:09:56 +0800 CST2024-06-13 09:09:56 +0800 CST 2024-06-13 09:09:56 +0800 CST

Existe uma maneira de executar um pipeline ou sair do shell após iniciar um pipeline?

  • 772

Estou escrevendo um script wrapper de shell que deve funcionar como um pager (recebendo entrada em stdin e executando saída em um tty).

Este wrapper prepara o ambiente e as linhas de comando e, em seguida, inicia dois processos em um pipeline: o primeiro é um filtro não interativo e o último é o pager real que precisa controlar um tty (ou melhor, gera o próprio pager real) :

#!/bin/bash

...

col -bx | bat "${bat_args[@]}" --paging=always

A árvore de processos resultante é assim:

<parent>
\- wrapper.sh
   |- col -bx (dies)
   \- bat ...
      \- less ...

O col -bxprocesso sai após filtrar a entrada e é colhido pelo shell.


É possível se livrar do processo shell, de modo que ele não permaneça enquanto o pager estiver em execução?

Pensei em uma solução alternativa usando substituição de processo:

exec bat "${bat_args[@]}" --paging=always < <(col -bx)

Porém, o col -bxprocesso não é colhido pelo shell e permanece no estado Z. Existe uma maneira "certa" de escrever esse wrapper?

bash
  • 1 1 respostas
  • 44 Views

1 respostas

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2024-06-13T13:30:55+08:002024-06-13T13:30:55+08:00

    Você também pode fazer:

    #!/bin/zsh -
    col -bx | exec bat "${bat_args[@]}" --paging=always
    

    Ou:

    #!/bin/ksh -
    col -bx | exec bat "${bat_args[@]}" --paging=always
    

    (não com as implementações de ksh derivadas de pdksh)

    #!/bin/bash -
    
    shopt -s lastpipe
    col -bx | exec bat "${bat_args[@]}" --paging=always
    

    No final, funcionalmente equivalente ao que você faz com um redirecionamento de uma substituição de processo, mas pule aquele embaralhamento extra de fd e a criação de pipe nomeado (ou /dev/fd/xabertura em sistemas que os possuem (a maioria)).

    Em qualquer caso, para colher um processo, é preciso esperar por ele. Com ksh// e as abordagens acima, será um filho do processo que eventualmente executa , então receberá um SIGCHLD quando morrer, o que ele fará com zshele depende dele. Se ele não lidar com o SIGCHLD (poucos aplicativos o fazem para processos que eles próprios não geraram), será exibido como um zumbi até o término, após o qual o processo será re-parentado para o sub-reaper filho ou e cuidado de lá.bash -O lastpipecolbatbatcolcolbatcolinit

    De qualquer forma, observe que em A | B, ksh não espera por Anenhum dos dois, a menos que você defina a pipefailopção.

    Agora, por POSIX na opção XSI , e isso também se aplica ao Linux,

    Se o processo pai do processo chamador configurou seu sinalizador SA_NOCLDWAIT ou configurou a ação para o sinal SIGCHLD como SIG_IGN :

    • As informações de status do processo (ver Informações de Status), se houver, deverão ser descartadas.
    • A vida útil do processo de chamada terminará imediatamente. Se SA_NOCLDWAIT estiver definido, será definido pela implementação se um sinal SIGCHLD será enviado ao processo pai.
    • Se um thread no processo pai do processo de chamada estiver bloqueado em wait(), waitpid() ou waitid(), e o processo pai não tiver nenhum processo filho restante no conjunto de filhos esperados, o wait(), A função waitid() ou waitpid() falhará e definirá errno como [ECCHILD].

    De outra forma:

    • Informações de status (consulte Informações de status) serão geradas.
    • O processo de chamada deve ser transformado em um processo zumbi . Suas informações de status devem ser disponibilizadas ao processo pai até que termine a vida útil do processo.
      [...]

    (ênfase minha).

    Agora, nem todos os shells permitirão que você ignore o SIGCHLD, sendo tão essencial para o seu funcionamento (o objetivo dos shells é executar comandos e relatar seu status de saída), mas parece com as versões atuais de bash(5.2.21 no meu teste) pelo menos faça, então em:

    #!/bin/bash -
    
    shopt -s lastpipe
    trap '' CHLD
    col -bx | exec bat "${bat_args[@]}" --paging=always
    

    O processo em execução colnunca se tornaria um zumbi, desde que batnão ignore o SIGCHLD antes de colsair.

    De qualquer forma, os zumbis não são necessariamente uma coisa ruim. O estágio zumbi faz parte do processo da vida, a maioria dos processos passa por lá entre o momento em que morrem e seus pais (ou initfilho sub-ceifador) reconhecem isso.

    • 1

relate perguntas

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve