Zsh / Tmux: Aguarde o sucesso do subprocesso

1

Consulte esta pergunta sem resposta antes de continuar: Tmux: verifique o código de saída do comando que foi enviado por chaves de envio

tmux send-keys apenas envia o comando e sai com sucesso, mas repeat 5; do print This is a test; sleep 1; done continua a ser executado como um subprocesso - não em uma subcamada.

Caso eu precise ter certeza de que repeat 5; do print This is a test; sleep 1; done foi feito antes de fazer outro tmux send-keys .

Como eu poderia conseguir isso com o zsh?

EDIT: @ Stéphane Chazelas: Eu gostaria de estender ou tornar a questão mais clara:

No caso de um script zsh que contenha vários comandos send-keys , conforme abaixo:

send-keys 'command1_run_as_subprocess_with_unpredictable_time_to_complete' Enter
send-keys 'command2_run_as_subprocess_with_unpredictable_time_to_complete' Enter
send-keys 'command3_run_as_subprocess_with_unpredictable_time_to_complete' Enter
<...>

Cada send-keys tem que esperar pelo anterior totalmente concluído antes de ser executado.

Como sua solução se aplicaria ao caso acima ?:

typeset -A pane_pid=($(for t (id index) tmux lsp -F "#{pane_$t} #{pane_pid}"))

pid=$pane_pid[%0] # pid of process started in first pane
    
por Tuyen Pham 19.09.2018 / 14:15

1 resposta

1

Suponho que você possa esperar até que o shell em execução nesse painel do tmux seja lido novamente no dispositivo do terminal:

Se no Linux,

until grep -qw tty_read "/proc/$pid/stack"; do sleep 1; done

em que $pid é o ID do processo desse shell.

Ou com mais eficiência e com um atraso menor com zsh :

zmodload zsh/zselect
until [[ $(</proc/$pid/stack) = *tty_read* ]] zselect -t 10

Observe que você precisa de /proc/sys/kernel/yama/ptrace_scope para conter 0 para que isso funcione (para que os processos possam analisar o que outros processos estão fazendo assim). Tenha em atenção que a alteração desse valor para 0 (com sudo sysctl -w kernel.yama.ptrace_scope=0 ) reduz ligeiramente a segurança do sistema.

Para obter um mapeamento entre o id do painel tmux ou o índice e o pid do processo em que ele foi executado, você pode fazer:

typeset -A pane_pid=($(for t (id index) tmux lsp -F "#{pane_$t} #{pane_pid}"))

pid=$pane_pid[%0] # pid of process started in first pane

Portanto, combinar os dois:

zmodload zsh/zselect
wait_for_shell_on_pane_to_read_tty() {
  local pane=$1
  local -A pane_pid=($(for t (id index) tmux lsp -F "#{pane_$t} #{pane_pid}"))
  until [[ $(</proc/$pane_pid[$pane]/stack) = *tty_read* ]] zselect -t 10
}

pane=%0 # replace with the pane you want to send those commands to
        # see tmux lsp for the list of panes

for cmd (
  'repeat 5; do print This is a test; sleep 1; done'
  command1_run_as_subprocess_with_unpredictable_time_to_complete
  command2_run_as_subprocess_with_unpredictable_time_to_complete
  command3_run_as_subprocess_with_unpredictable_time_to_complete
) {
  wait_for_shell_on_pane_to_read_tty $pane
  tmux send-keys -t $pane $cmd Enter
}

Note que, como estamos enviando essas linhas de comando em seqüência sem atraso entre elas, o shell no painel ainda pode estar lendo o tty após termos enviado o primeiro comando (e ainda não o executamos), o que poderia fazer com que várias linhas de comando fossem enviadas de uma só vez.

    
por 19.09.2018 / 14:27

Tags