Come posso eseguire lo stesso comando linux in più di una scheda / shell contemporaneamente?


33

Esistono strumenti / comandi in Linux che posso usare per eseguire un comando in più di una scheda contemporaneamente? Voglio eseguire lo stesso comando: ./myprog argument1 argument2simultaneamente in più di una shell per verificare se i mutex funzionano bene in un programma thread. Voglio essere in grado di aumentare il numero di istanze di questo programma in modo da mettere il mio codice sotto stress in seguito.

Sto cercando qualcosa come quello che fa il muro. Posso pensare di usare tty's, ma mi sembra molto doloroso se devo ridimensionarlo a molte più shell.


1
"Ogni volta che ti ritrovi a svolgere un'attività ripetitiva che coinvolge un computer, automatizzalo" - io . Penso che potresti farti un disservizio usando più schede terminali per i test di carico perché dovresti guardarli tutto ciò che è noioso. Meglio avere un programma che genera myprogistanze figlio e aggrega l'output per te.
msw,

1
Il multi-threading normale non avrà un mutex tra i processi ...?
Aaron D. Marasco

@msw: Sì, ma se volessi vedere cosa vedrebbe l'utente finale quando eseguisse lo stesso comando dal suo terminale e quando lo ridimensionassi per dire 100, cosa vedrebbero sul loro schermo? Non è una cosa valida da determinare?
Arpith,

@ AaronD.Marasco: voglio controllare i mutex che ho inserito, nello spazio utente.
Arpith,

Quindi esegui 99 istanze sotto un supervisore ed esegui un centesimo in un terminale. Ammetto che potresti essere in grado di guardare 100 terminali contemporaneamente, in tal caso, sono impressionato.
msw,

Risposte:


46

Come già suggerito mavillan, basta usare terminator . Permette di visualizzare molti terminali in modo piastrellato. Quando si abilita la funzione di trasmissione, è possibile immettere lo stesso comando contemporaneamente su ciascun terminale.

Ecco un esempio con il comando data trasmesso su una griglia di 32 terminali.

terminatorx32


3
Accidenti è fantastico!
Afr

Come posso aprire facilmente 32 terminali?
Annan,

6
@Annan Terminator supporta layout personalizzati, dai un'occhiata a unix.stackexchange.com/a/168445/2594 e askubuntu.com/a/178242/18306
jlliagre

11

tmux ha questa capacità. (insieme a molte altre utili capacità nella stessa vena)

Può essere fatto tramite:

:setw synchronize-panes on

potresti per favore descrivere brevemente come lo fa tmux o incollare un link? grazie!
eli

1
: visualizza i riquadri di sincronizzazione
Michael Martinez,

9

Multixterm

Un altro strumento da aggiungere all'elenco è quello chiamato multixterm. Usa i xtermterminali. Puoi invocarlo in questo modo:

$ multixterm

E una volta su ti verrà presentata una GUI.

                                                         ss di gui

È quindi possibile iniziare a girare le xtermfinestre facendo clic sul new xtermpulsante. Qui ad esempio ho invocato 2. Se poi fai clic sulla finestra principale, puoi iniziare a digitare i comandi in entrambe le finestre contemporaneamente:

   ss di xtems

keyboardcast

Sembra essere disponibile solo su Ubuntu, sembra simile a multixterm.

estratto

Lo scopo di Keyboardcast è di consentire l'invio di sequenze di tasti a più X finestre contemporaneamente. Ciò consente, ad esempio, di controllare un numero di terminali collegati a host diversi ma simili ai fini dell'amministrazione di massa.

Puoi anche selezionare non terminali. Se ti viene in mente un uso ragionevole di questa capacità, sarei interessato a sentirne parlare.

Il programma può selezionare le finestre a cui inviare sia abbinando i loro titoli (usando una sottostringa) o facendo clic su di essi (in un metodo simile alla funzione di screenshot di GIMP).

Il programma offre anche la possibilità di generare più istanze di gnome-terminal eseguendo un singolo comando su più argomenti (ad esempio eseguendo 'ssh' su più host). I terminali gnome vengono invocati con il profilo "keyboardcast" se esiste (quindi, ad esempio, la dimensione del carattere può essere inferiore).


custodi! Nota presa.
runlevel0

Sembra che il keycast sia interrotto, il che è deludente.
RJ


8

Puoi fare qualcosa del tipo:

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

Oppure se l'output di ciascun comando è rilevante durante l'esecuzione, è possibile impostare la schermata.

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

Lo schermo richiede più lavoro manuale.


Potresti espandere di più sulla soluzione dello schermo? Più in linea con quello che voglio ...
Arpith,

perché non solo tail -fil file di registro anziché impostare un centinaio di schermate.
Lie Ryan

@Arpith lo schermo genera diversi terminali in uno solo. Se vuoi vederli tutti in "tempo reale", puoi usare lo schermo. Anche se personalmente andrei con i file di log, puoi impostare il tuo prog per inviare un messaggio o effettivamente avere il tuo prog che scrive un file di log per ogni istanza (es: myprog.pid.log)
BitsOfNix

@LieRyan perché, a meno che tu non stia effettuando l'accesso con qualcosa come syslog, devi accedere a un file separato per ogni processo. Se provi semplicemente ad avere più di 20 processi, scrivi nello stesso file allo stesso tempo, avrai dei brutti momenti.
Sammitch,

@Sammitch:tail -f *.log
Lie Ryan

5

Sono un utente KDE, con konsole 2.13.2 su KDE 4.13.3 puoi farlo:

  1. Konsole aperta

  2. vista divisa in verticale inserisci qui la descrizione dell'immagine

  3. scrivere simultaneamente su ciascun terminale all'interno della finestra inserisci qui la descrizione dell'immagine


4

Prova Terminator (terminale dell'emulatore). Può avere molte sessioni di shell nella stessa finestra e puoi trasmettere un comando a tutte.

Terminator


3

Puoi usare uno strumento come MobaXterm e ti permetterà di connetterti simultaneamente e quindi incollare i tuoi comandi in tutte le finestre.


Non collegato a Linux, come mobaxterm, molto impressionante per quello che fa, è solo Windows e la domanda riguarda chiaramente una soluzione Linux.
RJ

3

Se si desidera vedere solo l'output dell'esecuzione del 100 ° programma:

#!/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

2

Puoi controllare konsoleattraverso DCOP. Un esempio è da qui :

#!/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.

2
sh <<-STRESS & 
$( printf 'myprog &\n%.0b' \
    `seq 1 ${MAX_CONCURRENT_PROCS}` )
STRESS
echo "$!"

Sono d'accordo con il commento che @msw fa sopra. Questo ti scriverà uno script da avviare con un shprocesso in background e stamperà il shpid del processo figlio in modo da poterlo monitorare e i suoi figli mentre funziona.


2

@Jinpeng era sulla buona strada con GNU Parallel , ma non l'implementazione.

Esempio: esegui 10 istanze parallele del tuo programma, con ogni thread che esegue il programma una sola volta:

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

Esempio: esegui 10 thread paralleli, con ognuno di quei thread che eseguono il tuo programma all'infinito:

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

Puoi facilmente ridimensionarlo a centinaia di thread sostituendo il 10nei miei esempi.

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

Se il tuo programma produce messaggi stdout e vuoi vederli man mano che vengono prodotti (piuttosto che il valore predefinito che li raccoglie), l' --ungroupopzione in parallelo può essere utile.

parallel --ungroup   ...

Se stai eseguendo molti thread dalla tua workstation e non vuoi che le cose non rispondano, considera nice l'intera sottostruttura del processo al momento del lancio.

nice -n19 parallel   ...

Nota a margine, GNU parallela di solito non è installato per impostazione predefinita, ma è di solito nelle vostre normali pronti contro termine del pacchetto, quindi basta installarlo come qualsiasi altro pacchetto: dnf install parallel, apt-get install parallel, brew install parallel, etc.


1

È possibile avviare i processi in background con nohup .

Esempio:

nohup ./myprog -arg1 -arg2 &

Produzione:

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

Ricorda di terminare l'attività in seguito con il dato PID:

kill 1769

Per portare il processo in primo piano è necessario inserire il numero di lavoro, in questo caso [1]:

fg %1

1

gnu parallel è esattamente lo strumento che stai cercando. parallel -j 9 yourcommand


0

Il mio piccolo da macinare:

#!/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

Configura il terminatore (termini di layout) per molte finestre in un gruppo.

EDIT: almeno, terminator è in grado di inviare broadcast in tutti i terminali dello stesso gruppo. Questa funzione è commutabile - quindi puoi abilitarla scrivere 'su' 'quindi disabilitare e scrivere owen password sui terminali onces e abilitarla di nuovo.


1
È meglio? Mi scusi per il malessere inglese, per favore :)
Marek,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.