Como enviar um comando para todos os painéis no tmux?

189

Eu gosto de chamar :clear-historypainéis com uma enorme rolagem. No entanto, quero criar um script para enviar este comando a todos os painéis nas várias janelas.

Sei como enviar um comando para todas as janelas, cortesia desta pergunta , mas como envio um comando para todos os painéis de que janela também?

send-keyse synchronize-panesda página de manual do tmux vêm à mente, mas não tenho certeza de como casar com eles. Mas talvez haja uma maneira mais simples de fazer isso.

Observações extras:

Pensando um pouco sobre isso, tmux list-panes -aparece listar todos os painéis na sessão atual. Muito útil para começar. Para onde eu vou daqui?

Ehtesh Choudhury
fonte
Para quem chega a essa pergunta na esperança de encontrar uma solução que se aplique a cada painel, em cada janela, em cada sessão: scripter.co/command-to-every-pane-window-session-in-tmux
chb

Respostas:

351

Você já tentou seguir na janela tmux com vários painéis

Ctrl-B :

setw synchronize-panes on

clear history
shailesh garg
fonte
52
Apenas por uma questão de completude, para desligar se você faria #Ctrl-b :setw synchronize-panes off
318 Mitch Mitch
19
e você pode vincular atalhos para isso ~/.tmux.confadicionando: bind -n C-x setw synchronize-panes on e bind -n M-x setw synchronize-panes off
guneysus
4
é possível definir o mesmo atalho para alternar?
Arnold Roa
20
@ArnoldRoa sim, a opção alternará se você sair on/off. Entãobind -n C-x setw synchronize-panes
sensação
1
Se eu adicionar bind -n C-x setw synchronize-panesqual atalho devo pressionar para chamar? É o prefixo + C & x. Eu tentei muitas opções
Bill Goldberg
28

Um pouco atrasado para a festa, mas eu não queria definir e desabilitar painéis de sincronização apenas para enviar um comando, então criei uma função de wrapper em torno do tmux e adicionei uma função personalizada chamada send-keys-all-panes.

_tmux_send_keys_all_panes_ () {
  for _pane in $(tmux list-panes -F '#P'); do
    tmux send-keys -t ${_pane} "$@"
  done
}

Também crio um wrapper em torno do comando tmux para simplificar a chamada dessa função (por conveniência). O wrapper e o código acima estão todos aqui .

Isso me permite executar tmux send-keys-all-panes <command> ou tmux skap <commandenviar <command>para todos os painéis.

Observe que o tmux é um alias à minha função de wrapper tmux_pp.

kshenoy
fonte
este é bash, mas pode-se fazer o mesmo no prompt de comando tmux, quero dizer fazendoprefix + :
Rho Phi
Não sei como ou se isso é possível. Qual é o seu cenário de caso de uso para o qual você precisa enviar um comando <prefix>:?
kshenoy
Eu recomendaria chamar o snippet bash ( : run "yourscript.sh yourargs..."); se o seu comando tiver saído, o painel ativo ou especificado exibirá os resultados até você pressionar q, mas, nesse caso, não deve. Claro que você pode alternar / vincular isso ao seu gosto. Como um aparte, os processos internos podem interpretar as teclas digitadas ou seus efeitos de maneira diferente; portanto, uma lista de permissões ou uma lista negra #{pane_current_cmd}podem ser necessárias. Eu tenho ctrl + k obrigado a enviar ctrl + le limpar histórico; isso funciona bem para conchas, mas derruba o buffer do Vim. Eu precisaria de aperfeiçoamento antes de poder transmitir meu ctrl + k.
John P
Isso pode ser mais um problema XY; o prompt de comando do Tmux é útil, mas parece que você o está usando porque não possui outro prompt de comando aberto. Você pode configurar uma ligação de chave - sem o prefixo, se desejar - para alternar e focar um painel extra com o shell de sua escolha, em vez de enviar <prefix>:antes de cada comando, perdendo a saída após sair do comando e todas as armadilhas que vem com a execução através do Tmux. Por exemplo, <prefix>:run "man cat"não resulta em homem aparecendo em , nem pidof manmesmo ps auxf | grep mancomo 'menos', meu pager atual para homem.
John P #
O link está morto
Mateusz Piotrowski
10

Atualização junho 2019

Ilustração rápida sobre como configurar sua própria ligação para painéis de sincronização .

Adicionado o seguinte no meu tmux.conf(os comentários certamente se aplicam à minha configuração geral):

# synchronize all panes in a window
# don't use control S, too easily confused
# with navigation key sequences in tmux (show sessions)
unbind C-S
bind C-Y set-window-option synchronize-panes

Agora, posso alternar a capacidade de sincronizar comandos em vários painéis com <C-a><C-y>.

(Sim, remapeei a tecla de ligação para Ctrl a).

arcseldon
fonte
4

Nenhuma das respostas acima funcionou para mim (tmux v2.3), mas isso aconteceu na linha de comando do bash:

for _pane in $(tmux list-panes -a -F '#{pane_id}'); do \
  tmux clear-history -t ${_pane}  ; done

Um script mais generalizado, para comandos tmux que não sejam 'clear-history', substituiria esse elemento apenas por um parâmetro, por exemplo. $ 1. Tenha cuidado se você pretende escrever um script para lidar com uma série de comandos tmux, pois "-t $ {_pane}" precisará ser aplicado a cada um.

Observe que o -aparâmetro para tmux list-panesé necessário para cobrir todos os painéis em todas as janelas em todas as sessões. Sem isso, apenas os painéis na janela atual do tmux serão afetados. Se você tiver mais de uma sessão do tmux aberta e quiser aplicar o comando apenas aos painéis da sessão atual, substitua -apor -s(Está tudo na página de manual do tmux).

Eu não tenho os pontos de modificação para comentar diretamente em cada uma das respostas acima, então aqui está o porquê eles não estavam trabalhando para mim:

O problema que tive com a resposta do @ shailesh-garg foi que a sincronização afetava apenas os comandos emitidos dentro dos painéis, não os comandos tmux emitidos usando os Ctrl-B :que estão fora dos painéis.

Os três problemas que tive com a resposta de @kshenoy foram:

  1. ele envia pressionamentos de tecla para dentro de um painel, não para a operação tmux desse painel; portanto, por exemplo, se alguém tivesse um shell bash em execução no painel e usasse o script para enviar "histórico limpo", esses seriam os pressionamentos de tecla que apareceria na linha de comando do bash. Uma solução alternativa seria enviar "tmux clear-history" ou pré-pendurar "tmux" em "$ @", mas não editei a resposta por causa de meus outros problemas com a resposta;
  2. Eu não conseguia descobrir como enviar um caractere de nova linha sem literalmente quebrar a linha;
  3. Mesmo quando eu fiz isso, enviar "tmux clear-history" não teve efeito.
user1404316
fonte
3

minha versão do tmux é 1.9a, e isso funciona para mim, uma chave é suficiente para ligar e desligar

bind-key X set-window-option synchronize-panes\; display-message "synchronize-panes is now #{?pane_synchronized,on,off}"
LIU YUE
fonte
2
tmux send-keys -t <session id> <command> C-m  

Substitua o "id da sessão" e o "comando" de acordo.

RJ
fonte
gostaria de dizer algo sobre esta língua estranha
Muhammad Omer Aslam
O que? Inglês não é difícil. Mas se você tem algo a dizer, diga.
RJ
4
:Dcara, você precisa adicionar alguma descrição à sua resposta, pois ela possui um texto muito mínimo e, por esse motivo, o Stackoverflow a detecta como spam ou postagem de baixa qualidade, basta adicionar alguns detalhes para que ela não apareça embaixo dela.
Muhammad Omer Aslam
6
Engraçado, a resposta aceita também não tem descrição e apenas o código, mas tanto faz.
RJ
0

Esta é a minha função utilitária para fazê-lo, apenas executando o comando quando não houver nada em execução no painel.

#!/bin/bash

_send_bash_command_to_session() {
    if [[ $# -eq 0 || "$1" = "--help" ]] ; then
        echo 'Usage: _send_bash_command_to_session $session_name what ever command you want: '
        return
    fi
    input_session="$1"
    input_command="${@:2}"
    for _pane in $(tmux list-panes -s -t ${input_session} -F '#{window_index}.#{pane_index}'); do
        # only apply the command in bash or zsh panes.
        _current_command=$(tmux display-message -p -t ${input_session}:${_pane} '#{pane_current_command}')
        if [ ${_current_command} = zsh ] || [ ${_current_command} = bash ] ; then
            tmux send-keys -t ${_pane} "${input_command}" Enter
        fi
    done
}

tmux_set_venv() {
    _current_session=$(tmux display-message -p '#{session_name}')
    _send_bash_command_to_session ${_current_session} workon $1
}

Exemplo direcionado a uma sessão chamada dev, ativando um python virtualenv em todos os painéis que estão dentro bashou zshevitando a execução do comando em painéis com vim ou qualquer outro executável:

_send_bash_command_to_session dev workon myvirtualenv

ou mais fácil de lembrar: fazê-lo na sessão atual:

tmux_set_venv myvirtualenv

Encontre meu arquivo de configuração com esta função.

phcerdan
fonte