Uso spesso più di un terminale (o emulatore di terminale) alla volta; e mentre in X posso copiare e incollare i comandi, oltre a non essere molto pratico, ovviamente non funziona sul vero TTY. La prima idea che mi viene in mente è qualcosa di simile:
command > /dev/sometty
Sfortunatamente, il command
viene eseguito prima è convogliato e nessun trucco come echo `command`
funzionerà, non importa quanti strani caratteri bash ($
, `
, "
, ecc.) ci sono. Quindi /dev/sometty
ottiene semplicemente del testo.
Il problema è che, a volte, vale anche la pena di reindirizzare quei comandi in un file, renderlo eseguibile, ecc., o in breve:creare uno script ed eseguirlo dal terminale appropriato. Ma è un sacco di lavoro. Ho pensato di creare uno script per creare questi file, per un'istruzione:
termpipe -e "command1\ncommand2\"command 1 argument\\n(s)\"" -t /dev/sometty
farebbe qualcosa del tipo:
- Invia i comandi, diciamo, a
/tmp/termpipe-20140208-153029-1.sh
- rendere il file eseguibile
- esegui il file nel terminale appropriato
- elimina lo script al termine dell'esecuzione
AFAIK, il problema è in 3. :questo non risolve nessun problema, mi servirebbe un altro termpipe
istanza per eseguire la prima sul terminale appropriato. E uno per quello. E un altro per questo, ad infinitum . Quindi non può funzionare. O può?...
La soluzione potrebbe essere quella di utilizzare una pipe denominata per terminale e, all'avvio di ciascuna, uno script direbbe alla pipe di inoltrare tutto ciò che riceve al terminale e quindi di eseguirla (come una sorta di demone ).
Penso che potrebbe funzionare ma non so come impostare lo script iniziale. Come posso? Come posso dire alla FIFO di fornire comandi in pipe per l'esecuzione del rispettivo terminale? Non conosco molto Bash, quindi apprezzerei le spiegazioni complete.
Risposta accettata:
In seguito, si può benissimo far funzionare l'ultimo tuo piano. Affinché il comando da inviare non venga elaborato dalla shell, deve essere sotto forma di stringa quando raggiunge la pipe (quindi echo "command"
, non echo `command`
). Quindi deve essere letto da un processo in background (come un demone , ma non necessariamente) avviato nel terminale appropriato. Dovrebbe essere valutato con lo stesso processo.
Ma è caldaia per avere uno script per pipe. Quindi generalizziamo creando uno script come term-pipe-r.sh
(non dimenticare di chmod +x
esso!):
#!/bin/bash
pipe=$1 # the pipe name is the first argument
trap 'rm -f "$pipe"' EXIT # ignore exit and delete messages until the end
if [[ ! -p $pipe ]]; then # if the pipe doesn't exist, create it
mkfifo $pipe
fi
while true # cycle eternally..
do
if read line <$ pipe; then
if [[ "$line" == 'close the term-pipe pipe' ]]; then
break
# if the pipe closing message is received, break the while cycle
fi
echo # a line break should be used because of the prompt
eval $line # run the line: as this script should be started
fi # in the target terminal,
done # the line will be run there.
echo "<pipe closing message>" # custom message on the end of the script
Quindi supponi di volere /dev/tty3
per ricevere comandi:vai lì, fai
./term-pipe-r.sh tty3pipe & # $1 will be tty3pipe (in a new process)
E per inviare comandi, da qualsiasi terminale (anche da sé):
echo "command" > tty3pipe
o per eseguire un file lì:
cat some-script.sh > tty3pipe
Nota che questo piping ignora file come .bashrc
e gli alias lì dentro, come alias ls='ls --color'
. Spero che questo aiuti qualcuno là fuori.
Modifica (nota:vantaggio del non demone ):
Sopra ho parlato del lettore di pipe che non è un demone necessariamente, ma in realtà ho verificato le differenze e in questo caso è molto meglio essere un semplice processo in background. Perché in questo modo, quando chiudi il terminale, viene visualizzato un EXIT
segnale (SIGHUP
, SIGTERM
, o qualsiasi altra cosa) viene ricevuto anche dallo script e la pipe viene quindi eliminata (vedere la riga che inizia con trap
nello script) automaticamente, evitando un processo e un file inutili (e forse altri se ci fosse tale reindirizzamento alla pipe inutile).
Modifica (automazione):
Tuttavia, è noioso dover eseguire uno script che (almeno io) probabilmente desideri la maggior parte del tempo. Quindi, automatizziamolo! Dovrebbe iniziare in qualsiasi terminale e una cosa che tutti loro leggono è .bashrc
. Inoltre, fa schifo dover usare ./term-pipe-r.sh
. Quindi, si può fare:
cd /bin # go to /bin, where Bash gets command names
ln -s /directory/of/term-pipe-r.sh tpr # call it tpr (terminal pipe reader)
Ora per eseguirlo avresti solo bisogno di tpr tty3pipe &
in /dev/tty3
quando vuoi. Ma perché farlo quando puoi farlo automaticamente? Quindi questo dovrebbe essere aggiunto a .bashrc
. Ma aspetta:come farà a conoscere il nome della pipe? Può basare il nome sul TTY (che può essere conosciuto con il tty
comando), utilizzando semplici REGEX in sed
(e alcuni trucchi). Cosa dovresti aggiungere a ~/.bashrc
sarà quindi:
pipe="$(sed 's/\/dev\///' <<< `tty` | sed 's/\///')pipe"
# ^^^- take out '/dev/' and other '/', add 'pipe'
tpr $pipe & # start our script with the appropriate pipe name