Eu gostaria de executar algo como isto:
bash -c "some_program with its arguments"
mas para ter uma festa interativa, continue executando após o some_program
término.
Tenho certeza que -c
não é uma boa maneira, como man bash
seys:
Um shell interativo é aquele iniciado sem argumentos de não opção e sem a opção -c
Então, como fazer isso?
O objetivo principal é descrito aqui
NOTA
- Preciso terminar
some_program
de tempos em tempos - Eu não quero colocá-lo em segundo plano
- Eu quero ficar no
bash
então para fazer outra coisa - Quero poder executar o programa novamente
pty.
fg
Respostas:
É melhor fazer isso a partir de um script, embora com
exec $0.
Ou, se um desses descritores de arquivo direcionar para um dispositivo de terminal que não está sendo usado no momento, ajudará - você deve se lembrar, outros processos também querem verificar esse terminal.E, a propósito, se seu objetivo é, como presumo, preservar o ambiente do script após executá-lo, você provavelmente será muito melhor atendido:
O shell
.dot
ebash's source
não são o mesmo - o shell.dot
é POSIX especificado como um shell especial embutido e, portanto, está o mais próximo possível de ser garantido, embora isso não seja de forma alguma uma garantia de que estará lá ...Embora o acima deve fazer o que você espera com pouco problema. Por exemplo, você pode:
O shell executará seu script e o levará ao prompt interativo - desde que você evite
exit
o shell do script, ou seja, faça um background de seu processo - que vinculará sua E / S ao/dev/null.
DEMO:
MUITOS
JOBS
É minha opinião que você deve se familiarizar um pouco mais com as opções internas de gerenciamento de tarefas do shell. O @Kiwy e o @jillagre já abordaram isso em suas respostas, mas isso pode exigir mais detalhes. E eu já mencionei um shell especial específico do POSIX embutido, mas
set, jobs, fg,
ebg
são mais alguns, e, como outra resposta demonstratrap
ekill
são mais dois ainda.Se você ainda não está recebendo notificações instantâneas sobre o status de processos em segundo plano em execução simultaneamente, é porque suas opções atuais de shell estão definidas no padrão especificado pelo POSIX
-m
, mas você pode obtê-las de forma assíncronaset -b
:Uma característica muito fundamental dos sistemas baseados em Unix é o método de manipulação de processos
signals
. Certa vez, li um artigo esclarecedor sobre o assunto que compara esse processo à descrição de Douglas Adams do planeta NowWhat:Isso está se referindo
kill signals
.Pelo menos para mim, a citação acima respondeu a muitas perguntas. Por exemplo, sempre achei muito estranho e nada intuitivo que, se quisesse monitorar um
dd
processo, fosse necessáriokill
. Depois de ler isso, fez sentido.Eu diria que a maioria deles não tenta se adaptar por um bom motivo - pode ser um aborrecimento muito maior do que um benefício ter vários processos enviando spam ao seu terminal com qualquer informação que seus desenvolvedores pensassem que poderia ser importante para você .
Dependendo da configuração do terminal (com a qual você pode verificar
stty -a
) ,CTRL+Z
é provável que seja encaminhado aSIGTSTP
para o atual líder do grupo de processos em primeiro plano, que provavelmente é seu shell e que também deve ser configurado por padrão paratrap
esse sinal e suspender seu último comando. Novamente, como mostram as respostas de @jillagre e @Kiwy juntas, não há como impedir que você adapte essa funcionalidade ao seu objetivo, como preferir.SCREEN JOBS
Portanto, para tirar proveito desses recursos, é esperado que você os entenda primeiro e personalize seu manuseio de acordo com suas próprias necessidades. Por exemplo, eu encontrei este screenrc no Github que inclui
screen
ligações de teclas paraSIGTSTP
:Isso tornaria simples suspender um processo em execução como um
screen
processo filho ou oscreen
próprio processo filho, como você desejasse.E imediatamente depois:
OU:
Primeiro ou segundo plano o processo como você preferir. O
jobs
built-in pode fornecer uma lista deles a qualquer momento. A adição do-l
operando incluirá detalhes do pid.fonte
Aqui está uma solução mais curta que realiza o que você deseja, mas pode não fazer sentido, a menos que você entenda o problema e como o bash funciona:
Isso iniciará um shell bash, iniciará
some_program
e, após assome_program
saídas, você será direcionado para um shell bash.Basicamente, o que estamos fazendo é alimentar o bash com uma string do STDIN. Essa string é
some_program with its arguments; exec </dev/tty
. Isso informa ao bash para iniciarsome_program
primeiro e depois executarexec </dev/tty
. Então, em vez de continuar lendo os comandos da string que passamos, o bash começará a ler/dev/tty
.O
-i
é porque quando o bash é iniciado, ele verifica para ver se STDIN é um tty, e quando ele começa não é. Mas mais tarde será, então forçamos o modo interativo.Outra solução
Outra idéia que pensei que seria muito portátil seria adicionar o seguinte ao final do seu
~/.bashrc
arquivo.Então, quando você deseja iniciar um shell com um comando primeiro, basta:
Explicação:
A maior parte disso deve ser óbvia, mas o resson para o nome da variável que muda o material é para que possamos localizar a variável. Como
$START_COMMAND
é uma variável exportada, ela será herdada por qualquer filho do shell e, se outro shell bash for um desses filhos, ele executará o comando novamente. Portanto, atribuímos o valor a uma nova variável não exportada ($start_command
) e excluímos a antiga.fonte
<<<
não é POSIX, mas você poderiaecho "string here" | bash -i
. Depois, há o/dev/tty
que é uma coisa do linux. Mas você pode enganar o FD antes de iniciar o bash e reabrir o STDIN, que é semelhante ao que você está fazendo, mas optei por manter as coisas simples./dev/tty
não é uma coisa do Linux, mas definitivamente POSIX.Isso deve fazer o truque:
Editar:
Aqui está uma nova tentativa após sua atualização:
Use ControlC, você verá este pequeno menu:
Esse é o caso
Selecione a opção "bash"
Selecione a opção "reiniciar"
fonte
CTRL+C
é apenas um efeito colateral da configuração padrão do seu terminal para interpretá-lo como umSIGINT
. Você pode modificar isso como quiserstty
.SIGINT
estátrapped
acima de2
.Você pode fazer isso passando seu script como um arquivo de inicialização:
Ou você pode transmiti-lo na linha de comando:
Observe que isso
--init-file
foi feito para a leitura de arquivos de inicialização em todo o sistema,/etc/bash.bashrc
assim, você pode "source
" desejá- los em seu script.fonte
Eu realmente não vejo o objetivo de fazer isso, já que você já volta para um shell depois de executar este programa. No entanto, você pode fazer isso:
Isso iniciará um bash interativo após a execução do programa.
fonte
Você pode colocar o comando em segundo plano para manter seu bash atual aberto:
Para retornar à execução, você pode usar o
fg
comando e^+z
colocá-lo em segundo plano novamentefonte
bash
ou não, você está usando um shell muito estranho para mim, se ele não consegue lidar com o processo em segundo plano. E eu concordo com Kiwi - essas informações o serviriam melhor se estivessem na sua pergunta.Você pode usar a tela para executar o comando. Em seguida, você pode reconectar à sessão após a conclusão do comando.
Como alternativa, basta executar o comando em segundo plano
some_program with its arguments&
. Isso permitirá que você execute novamente o comando e obtenha o status do comando depois que ele for concluído.fonte
screen
mas colocá-lo em segundo plano não é útil para mim - às vezes preciso encerrar o programa, fazer outra coisa e executá-lo novamente. E o objetivo principal é fazer isso rápido.kill %
oukill %1
.