Como executo o mesmo comando linux em mais de uma guia / shell simultaneamente?

33

Existe alguma ferramenta / comando no Linux que eu possa usar para executar um comando em mais de uma guia simultaneamente? Eu quero executar o mesmo comando: ./myprog argument1 argument2simultaneamente em mais de um shell para verificar se os mutexes estão funcionando bem em um programa encadeado. Quero poder aumentar o número de instâncias desse programa para colocar meu código sob estresse mais tarde.

Eu estou procurando algo como o que a parede faz. Eu posso pensar em usar tty's, mas isso parece muita dor se eu precisar escalar isso para muito mais conchas.

Arpith
fonte
1
"Sempre que você se encontrar fazendo uma tarefa repetitiva que envolve um computador, automatize-o" - eu . Eu acho que você pode estar fazendo um desserviço usando várias guias de terminal para o teste de carga, porque você teria que assistir a todos, o que é tedioso. Melhor ter um programa que gera myproginstâncias filho e agrega sua saída para você.
RSU
1
O multi-threading normal não terá um mutex entre processos ...?
Aaron D. Marasco
@ msw: Sim, mas e se eu quisesse ver o que o usuário final veria quando executasse o mesmo comando em seu terminal e quando eu escalasse isso para dizer 100, o que eles veriam na tela? Isso não é uma coisa válida para determinar?
Arpith
@ AaronD.Marasco: Quero verificar os mutexes que inseri, no espaço do usuário.
Arpith
Portanto, execute 99 instâncias sob um supervisor e execute uma centésima em um terminal. Concordo que você possa assistir a 100 terminais simultaneamente; nesse caso, estou impressionado.
RSU

Respostas:

46

Como mavillan já sugeriu, basta usar o terminator . Permite exibir muitos terminais de maneira lado a lado. Ao ativar o recurso de transmissão, você pode inserir o mesmo comando simultaneamente em cada terminal.

Aqui está um exemplo com o comando date transmitido para uma grade de 32 terminais.

terminatorx32

jlliagre
fonte
3
Porra, isso é incrível!
Afr
Como abrir facilmente 32 terminais?
Annan
6
O @Annan Terminator suporta layouts personalizados, consulte unix.stackexchange.com/a/168445/2594 e askubuntu.com/a/178242/18306
jlliagre
11

O tmux tem esse recurso. (junto com muitos outros recursos úteis na mesma linha)

Pode ser feito via:

:setw synchronize-panes on
Michael Martinez
fonte
você poderia em breve descrever como o tmux faz isso - ou colar um link? THX!
eli
1
: Sincronizar-panes setw sobre
Michael Martinez
9

Multixterm

Outra ferramenta para adicionar à lista é uma chamada multixterm. Ele usa xtermterminais. Você pode invocá-lo assim:

$ multixterm

E uma vez instalado, você receberá uma GUI.

                                                         ss de gui

Você pode começar a girar as xtermjanelas clicando no new xtermbotão Aqui, por exemplo, chamei 2. Se você clicar na janela principal, poderá começar a digitar comandos nas duas janelas simultaneamente:

   ss de xtems

keyboardcast

Parece estar disponível apenas no Ubuntu, é semelhante ao multixterm.

excerto

O objetivo do teclado é permitir que você pressione as teclas para várias janelas do X ao mesmo tempo. Isso permite, por exemplo, controlar vários terminais conectados a hosts diferentes, mas similares, para fins de administração em massa.

Você também pode selecionar não terminais. Se você usar um uso razoável dessa capacidade, eu estaria interessado em ouvir sobre isso.

O programa pode selecionar janelas para enviar, combinando seus títulos (usando uma substring) ou clicando neles (em um método semelhante ao recurso de captura de tela do GIMP).

O programa também possui a capacidade de gerar várias instâncias do gnome-terminal executando um único comando em vários argumentos (por exemplo, executando 'ssh' em vários hosts). Os terminais gnome são chamados com o perfil 'keyboardcast', se existir (por exemplo, o tamanho da sua fonte pode ser menor).

slm
fonte
detentores! Nota tomada.
amigos estão
Parece que o teclado está quebrado, o que é decepcionante.
RJ
8

Você pode fazer algo como:

max_processes=20
for ((i=0; i<$max_processes; i++))
do 
    /path/to/myprog arg1 arg2 > /tmp/myprog.${i}.log &
done

Ou, se a saída de cada comando for relevante durante a execução, você poderá configurar a tela.

vi ~/.screenrc
screen -t inst1    1 /path/to/myprog arg1 arg2
screen -t inst2    2 /path/to/myprog arg1 arg2
screen -t inst3    3 /path/to/myprog arg1 arg2
screen -t inst4    4 /path/to/myprog arg1 arg2

A tela requer mais trabalho manual.

BitsOfNix
fonte
Você poderia expandir mais na solução de tela? Mais em linha com o que eu quero ...
Arpith
por que não apenas tail -fo arquivo de log em vez de configurar centenas de telas.
Lie Ryan
@Arpith a tela gera vários terminais em um único. Se você quiser ver todos eles em "tempo real", poderá usar a tela. Embora, pessoalmente, eu iria com arquivos de log, você pode configurar o seu prog para enviar uma mensagem ou realmente ter o seu próprio prog escrevendo um arquivo de log para cada instância (ex: myprog.pid.log)
BitsOfNix
@LieRyan porque, a menos que você esteja registrando algo como o syslog, precisará registrar em um arquivo separado para cada processo. Se você simplesmente tentar ter mais de 20 processos gravados no mesmo arquivo ao mesmo tempo, terá um mau momento.
Sammitch 4/09/13
@Sammitch:tail -f *.log
Lie Ryan
5

Eu sou um usuário do KDE, com o konsole 2.13.2 no KDE 4.13.3, você pode fazer isso:

  1. konsole aberto

  2. dividir vista verticalmente insira a descrição da imagem aqui

  3. escreva simultaneamente em cada terminal dentro da janela insira a descrição da imagem aqui

nulll
fonte
4

Experimente o Terminator (terminal do emulador). Pode ter muitas sessões de shell na mesma janela e você pode transmitir um comando para todas elas.

Exterminador do Futuro

mavillan
fonte
3

Você pode usar uma ferramenta como o MobaXterm e ela permitirá que você se conecte simultaneamente e cole seus comandos em todas as suas janelas.

user46436
fonte
Não relacionado ao Linux, como mobaxterm, bastante impressionante pelo que faz, é apenas o Windows e a questão é claramente sobre uma solução Linux.
RJ
3

Se você deseja apenas ver a saída da 100ª execução do programa:

#!/bin/bash

prog="/path/to/myprog"
args="argument1 argument2"
max=100
for i in $(seq $max); do
    if [ $i -lt $max ]; then
        exec $prog $args &> /dev/null &
    else
        exec $prog $args
    fi
done
John B
fonte
2

Você pode controlar konsolecompletamente DCOP. Um exemplo é daqui :

#!/bin/bash

checkfile() {
  if [ ! -f $1 ]; then
    echo "could not find $1"
    exit 99
  else
    echo "OK"
  fi
}

# Check for App1 XML
echo -n "Checking for App 1 XML... "
XMLA=/domain/DM.xml
checkfile ${DEVROOT}/${XMLA}

# Check for App2 XML
echo -n "Checking for App 2 XML... "
hostname=$(hostname)
XMLB=/domain/DM_${hostname}.xml
checkfile ${DEVROOT}/${XMLB}

# Launch Konsole
echo -n "Launching konsole... "
K=$(dcopstart konsole-script)

[ -z "${K}" ] && exit 98
# Create second tab and resize
SDA=$(dcop $k konsole currentSession)
SDB=$(dcop $k konsole newSession)
dcop $K $SDA setSize 121x25

# Let bash login, etc.
sleep 1

# Rename the tabs
dcop $K $SDA renameSession "App 1"
dcop $K $SDB renameSession "App 2"

# Start services, letting user watch
echo -n "starting app1... "
dcop $K konsole activateSession $SDA
dcop $K $SDA sendSession "echo -ne '\033]0;DEV (${hostname})\007' && clear && starter $XMLA"
sleep 2
echo -n "starting app2... "
dcop $K konsole activateSession $SDB
dcop $K $SDB sendSession "echo -ne '\033]0;DEV (${hostname})\007' && clear && starter $XMLB"
echo done.
Aaron D. Marasco
fonte
2
sh <<-STRESS & 
$( printf 'myprog &\n%.0b' \
    `seq 1 ${MAX_CONCURRENT_PROCS}` )
STRESS
echo "$!"

Eu concordo com o comentário que o @msw faz acima. Isso escreverá um script para ser iniciado por um shprocesso em segundo plano e imprimirá o shpid do processo filho , para que você possa monitorá-lo e seus filhos enquanto ele funciona.

mikeserv
fonte
2

O @Jinpeng estava no caminho certo com o GNU Parallel , mas não a implementação.

Exemplo: Execute 10 instâncias paralelas do seu programa, com cada thread executando seu programa apenas uma vez:

parallel -j10 './myprog argument1 argument2 #' ::: {1..10}

Exemplo: Execute 10 threads paralelos, com cada um desses threads executando seu programa infinitamente:

parallel -j10 'while true ; do ./myprog argument1 argument2 ; done #' ::: {1..10}

Você pode escalar isso facilmente para centenas de threads, substituindo o dos 10meus exemplos.

parallel -j200     ...     ::: {1..200}

Se o seu programa produz mensagens stdout e você deseja vê-las como são produzidas (em vez do padrão que as agrupa), a --ungroupopção paralela pode ser útil.

parallel --ungroup   ...

Se você estiver executando muitos encadeamentos da estação de trabalho e não desejar que as coisas deixem de responder, considere nicea subárvore inteira do processo no momento da inicialização.

nice -n19 parallel   ...

Nota lateral, GNU Parallel normalmente não é instalado por padrão, mas é geralmente em seus repositórios de pacotes normais, então basta instalá-lo como qualquer outro pacote: dnf install parallel, apt-get install parallel, brew install parallel, etc.

Joshua Huber
fonte
1

Você pode iniciar processos em segundo plano com nohup.

Exemplo:

nohup ./myprog -arg1 -arg2 &

Saída:

[1] 1769    
nohup: ignoring input and appending output to 'nohup.out'

Lembre-se de matar a tarefa mais tarde com o dado PID:

kill 1769

Para trazer o processo em primeiro plano, você deve inserir o número do trabalho, neste caso [1]:

fg %1
TaXXoR
fonte
1

GNU paralelo é exatamente a ferramenta que você está procurando. parallel -j 9 yourcommand

Jingpeng Wu
fonte
0

Meu pequeno para moer:

#!/bin/sh

[ $# -lt 1 ] && {
        echo "Use: $0 <file>
        where file includes list of server"
        exit 9
}

cp ~/.config/terminator/config ~/.config/terminator/config.`date +%Y%m%d-%H%M`

cat ~/.config/terminator/config.`date +%Y%m%d-%H%M`|grep -v "^.plugins" >~/.config/terminator/config

inc=5
echo "  [[terms]]" >>~/.config/terminator/config
for i in `cat $1` ; do
        echo "   [[[window${inc}]]]"
        echo "       type = Window"
        echo "   [[[terminal${inc}]]]"
        echo "     profile = default"
        echo "     order = 0" 
        echo "     type = Terminal"
        echo "     parent = window${inc}"
        echo "     command = ssh $i"
        inc=$((inc+1))
done >>~/.config/terminator/config

echo "[plugins]" >>~/.config/terminator/config

Fará a configuração do terminador (termos de layout) para muitas janelas em um grupo.

EDIT: Pelo menos, o terminador pode enviar broadcast para todos os terminais do mesmo grupo. Esta função é selecionável - portanto, você pode habilitá-lo para escrever 'su -', depois desativar e escrever a senha devida nos terminais onces e habilitá-la novamente.

Marek
fonte
1
É melhor? Desculpe-me indisposto Inglês por favor :)
Marek