Acho difícil formular a pergunta com precisão, mas darei o meu melhor. Eu uso dwm
como meu gerenciador de janelas padrão edmenu
como meu iniciador de aplicativos. Eu quase não uso aplicativos GUI além do meu navegador. A maior parte do meu trabalho é feita diretamente na linha de comando. Além disso, sou um grande fã do minimalismo em relação a sistemas operacionais, aplicativos etc. Uma das ferramentas de que nunca me livrei foi o iniciador de aplicativos. Principalmente porque me falta uma compreensão precisa de como os ativadores de aplicativos funcionam / o que eles fazem. Até uma extensa pesquisa na Internet mostra apenas uma explicação vaga. O que eu quero fazer é me livrar do iniciador de aplicativos, porque, além de gerar o aplicativo, não tenho absolutamente nenhum uso para ele. Para fazer isso, eu realmente gostaria de saber como "corretamente" iniciar aplicativos a partir do shell. Por meio do qual o significado de "corretamente" pode ser aproximado por "como faria o iniciador de aplicativos".
Conheço as seguintes maneiras de gerar processos do shell:
exec /path/to/Program
substituir shell pelo comando especificado sem criar um novo processosh -c /path/to/Program
iniciar processo dependente do shell/path/to/Program
iniciar processo dependente do shell/path/to/Program 2>&1 &
processo independente do shell de lançamentonohup /path/to/Program &
inicie o processo independente do shell e redirecione a saída paranohup.out
Atualização 1: Eu posso ilustrar o que, por exemplo dmenu
, reconstruí-lo de chamadas repetidas para ps -efl
diferentes condições. Ele gera um novo shell /bin/bash
e, como filho desse shell, o aplicativo /path/to/Program
. Enquanto a criança estiver por perto, a concha estará por perto. (Como ele gerencia isso está além de mim ...) Por outro lado, se você emitir nohup /path/to/Program &
um shell /bin/bash
, o programa se tornará filho desse shell, mas se você sair desse shell, o pai do programa será o processo mais alto. Portanto, se o primeiro processo foi, por exemplo, /sbin/init verbose
e já foi PPID 1
, ele será o pai do programa. Aqui está o que eu tentei explicar usando um gráfico: chromium
foi lançado via dmenu
, firefox
foi lançado usando exec firefox & exit
:
systemd-+-acpid
|-bash---chromium-+-chrome-sandbox---chromium-+-chrome-sandbox---nacl_helper
| | `-chromium---5*[chromium-+-{Chrome_ChildIOT}]
| | |-{Compositor}]
| | |-{HTMLParserThrea}]
| | |-{OptimizingCompi}]
| | `-3*[{v8:SweeperThrea}]]
| |-chromium
| |-chromium-+-chromium
| | |-{Chrome_ChildIOT}
| | `-{Watchdog}
| |-{AudioThread}
| |-3*[{BrowserBlocking}]
| |-{BrowserWatchdog}
| |-5*[{CachePoolWorker}]
| |-{Chrome_CacheThr}
| |-{Chrome_DBThread}
| |-{Chrome_FileThre}
| |-{Chrome_FileUser}
| |-{Chrome_HistoryT}
| |-{Chrome_IOThread}
| |-{Chrome_ProcessL}
| |-{Chrome_SafeBrow}
| |-{CrShutdownDetec}
| |-{IndexedDB}
| |-{LevelDBEnv}
| |-{NSS SSL ThreadW}
| |-{NetworkChangeNo}
| |-2*[{Proxy resolver}]
| |-{WorkerPool/1201}
| |-{WorkerPool/2059}
| |-{WorkerPool/2579}
| |-{WorkerPool/2590}
| |-{WorkerPool/2592}
| |-{WorkerPool/2608}
| |-{WorkerPool/2973}
| |-{WorkerPool/2974}
| |-{chromium}
| |-{extension_crash}
| |-{gpu-process_cra}
| |-{handle-watcher-}
| |-{inotify_reader}
| |-{ppapi_crash_upl}
| `-{renderer_crash_}
|-2*[dbus-daemon]
|-dbus-launch
|-dhcpcd
|-firefox-+-4*[{Analysis Helper}]
| |-{Cache I/O}
| |-{Cache2 I/O}
| |-{Cert Verify}
| |-3*[{DOM Worker}]
| |-{Gecko_IOThread}
| |-{HTML5 Parser}
| |-{Hang Monitor}
| |-{Image Scaler}
| |-{JS GC Helper}
| |-{JS Watchdog}
| |-{Proxy R~olution}
| |-{Socket Thread}
| |-{Timer}
| |-{URL Classifier}
| |-{gmain}
| |-{localStorage DB}
| |-{mozStorage #1}
| |-{mozStorage #2}
| |-{mozStorage #3}
| |-{mozStorage #4}
| `-{mozStorage #5}
|-gpg-agent
|-login---bash---startx---xinit-+-Xorg.bin-+-xf86-video-inte
| | `-{Xorg.bin}
| `-dwm-+-dwmstatus
| `-xterm---bash-+-bash
| `-pstree
|-systemd---(sd-pam)
|-systemd-journal
|-systemd-logind
|-systemd-udevd
|-wpa_actiond
`-wpa_supplicant
Atualização 2: Acho que a pergunta também pode ser resumida em: Qual deve ser o pai de um processo? Por exemplo, deveria ser uma concha ou deveria ser o init
processo, ou seja, o processo com PID 1
?
init
- para qual a resposta pode ser ... talvez? depende de como / se você planeja conversar com ele, oinit
que usa e onde estão os canais de dados. Em geral, essas coisas tendem a se resolver -init
é para isso. De qualquer forma, geralmente quando você daemon um processoinit
. Ou, se você deseja controle do trabalho, shell atual.dmenu
e ver como me dou bem com o que aprendi. Achoexec /path/to/Program & exit
ou/bin/bash -c /path/to/Program & exit
para ser bastante utilizável. Mas todos eles fazem,1
ou seja,init
o pai doProgram
que está bem comigo, desde que isso faça sentido e não viole nenhum*nix
princípio básico .exec &
, eu acho. Normalmente faço minhas coisas no terminal ... talvez você se aproveite da pergunta de Ben Crowell aqui . Eu tenho uma resposta lá, mas todos eles são muito bons. de qualquer maneira, quando vocêsh -c 'cat & kill $$'
cria um processo em segundo plano e seu pai morre, você fica órfão e acaba sendo colhido eventualmente. esse é o trabalho do init - é por isso que todos caem nisso.systemd--bash--chromium
. Todos os métodos que eu tento acabarão levando a uma árvore de processos da seguinte formasystemd--chromium
quando eu gerar o Firefox do shell. Como a concha é demonizada aqui? Não está associado a nenhum terminal.Respostas:
Bem, você parece ter um bom entendimento disso. Para esclarecer um pouco do que você tem,
sh -c /path/to/Program
é bastante semelhante aonde você inicia um novo processo de shell, forneça o caminho de comando do aplicativo para o novo shell e deixe o novo shell terminar. Eu mostrei o novo shell dando um prompt diferente para fins de ilustração; isso provavelmente não aconteceria na vida real. A construção é útil principalmente para fazer coisas complicadas, como agrupar vários comandos em um pacote, para que pareçam um único comando (tipo de script não nomeado de uso único) ou para criar comandos complicados, possivelmente a partir de variáveis do shell. Você dificilmente o usaria apenas para executar um único programa com argumentos simples.
sh -c "command"
2>&1
significa redirecionar o erro padrão para a saída padrão. Isso realmente não tem muito a ver com&
; em vez disso, você o utiliza quando um comando envia mensagens de erro para a tela, mesmo que você diga e deseje capturar as mensagens de erro no arquivo.command > file
nohup.out
é um efeito colateral trivial denohup
. O principal objetivo de é executar de forma assíncrona (geralmente conhecida como "em segundo plano" ou como "processo independente do shell", para usar suas palavras) e configurá-lo para que tenha uma melhor chance de poder continuar sendo executado se você encerre o shell (por exemplo, logout) enquanto o comando ainda estiver em execução.nohup command &
command
bash(1)
e o Manual de Referência do Bash são boas fontes de informação.fonte
Existem algumas maneiras de executar um programa e desconectá-lo de um terminal. Um deles é para executá-lo em segundo plano de um subnível , como este (substitua
firefox
com seu programa favorito):Outra é negar o processo:
Se você está curioso sobre como lançadores de aplicativos de trabalho,
dmenu
fornece um binário e 2 scripts shell:dmenu
,dmenu_path
edmenu_run
, respectivamente.dmenu_run
canaliza a saída paradmenu_path
dentro do dmenu, que por sua vez canaliza para qualquer que seja sua$SHELL
variável definida. Se estiver vazio, ele será usado/bin/sh
.dmenu_path
é um pouco mais complexo, mas, em resumo, fornece uma lista de binários na$PATH
variável de ambiente e usa um cache, se possível.Não é necessário ter programas rodando em shell. Outra maneira de escrever
dmenu_run
, sem canalizar para um shell, seria:fonte
Eu gosto muito da resposta do G-Man. Mas estou respondendo porque acho que você está confundindo preocupações. Como Wayne ressalta, a melhor resposta é "o que obtiver os resultados desejados".
No gerenciamento de processos Unix, todo processo tem um pai. A única exceção é o
init
processo iniciado pelo sistema operacional na inicialização. É um comportamento normal de um processo pai levar todos os seus processos filhos quando ele morre. Isso é feito enviando o sinal SIGHUP para todos os processos filhos; o tratamento padrão do SIGHUP encerra o processo.A geração de shell dos processos do usuário não é diferente do que se você codificasse as chamadas fork (2) / exec (3) no idioma de sua escolha. O shell é seu pai e, se o shell terminar (por exemplo, você efetua logoff), o (s) processo (s) filho (s) gerado (s) o acompanha. As nuances que você descreve são apenas maneiras de modificar esse comportamento.
exec /path/to/program
é como chamar exec (3) . Sim, ele substituirá o seu shellprogram
, mantendo o pai que o lançou.sh -c /path/to/program
meio que inutilmente cria um processo de shell filho que criará um processo filho deprogram
. Só é valioso se/path/to/program
for realmente uma sequência de instruções de script, e não um arquivo executável. (sh /path/to/script.sh
pode ser usado para executar um script de shell que não possui permissões de execução em um shell inferior)/path/to/program
cria um processo de "primeiro plano", o que significa que o shell aguarda a conclusão do processo antes de executar qualquer outra ação. No contexto de chamada do sistema, é como fork (2) / exec (3) / waitpid (2) . Observe que o filho herda stdin / stdout / stderr do pai./path/to/program &
(ignorando o redirecionamento) cria um "processo em segundo plano". O processo ainda é filho do shell, mas o pai não está aguardando o término.nohup /path/to/program
chama nohup (1) para impedir o envio de SIGHUP paraprogram
se o terminal de controle estiver fechado. Seja em primeiro plano ou em segundo plano, é uma escolha (embora o processo seja mais comum em segundo plano). Observe quenohup.out
é apenas a saída se você não redirecionar o stdout.Quando você coloca um processo em segundo plano, se o processo pai morre, uma das duas coisas acontece. Se o pai for um terminal de controle , o SIGHUP será enviado aos filhos. Caso contrário, o processo pode ser "órfão" e é herdado pelo
init
processo.Ao redirecionar a entrada / saída / erro, você está simplesmente conectando os descritores de arquivo que todo processo possui a arquivos diferentes daqueles herdados de seu pai. Nada disso afeta a propriedade do processo ou a profundidade da árvore (mas sempre faz sentido redirecionar todos os 3 para longe de um terminal para processos em segundo plano).
Com tudo isso dito, não acho que você deva se preocupar com a criação de processos pelo shell ou subconchas ou subprocessos, a menos que exista um problema específico que você esteja abordando relacionado ao gerenciamento de processos.
fonte
sh -c /path/to/program
não executará o programa como um shell script se estiver faltando os bits executáveissh /path/to/program
.sh -c /path/to/program
apenas abrirá um shell e executará/path/to/program
como um comando nesse shell, que falhará se não for executável.sh -c /path/to/program
lê comandos de/path/to/program
como entrada para o shell. Ele não requer que o arquivo tem permissão de execução, mas deve ser um script shellsh /path/to/program
faz isso. Apenas tentei isso:,echo echo hello world >abc.sh
entãosh ./abc.sh
imprimehello world
, enquantosh -c ./abc.sh
dizsh: ./abc.sh: Permission denied
(que é o mesmo que se você executasse./abc.sh
o shell atual diretamente.) Perdi alguma coisa? (Ou talvez eu não me expressei bem no comentário anterior ...)sh -c _something_
é o mesmo que digitar_something_
no prompt de comando, exceto pela geração do shell inferior. Portanto, você está certo de que falhará se estiver faltando o bit de execução (como um arquivo). Por outro lado, você pode fornecer uma série de comandos do shellsh -c "echo hello world"
e ele funcionará perfeitamente. Portanto, não é necessário que o que você digita tenha o bit de execução (ou até mesmo um arquivo), apenas que o interpretador de shell possa fazer algo com ele.