GNU/Linux >> Linux Esercitazione >  >> Linux

Come inviare comandi a qualsiasi terminale?

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:

  1. Invia i comandi, diciamo, a /tmp/termpipe-20140208-153029-1.sh
  2. rendere il file eseguibile
  3. esegui il file nel terminale appropriato
  4. 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.

Correlati:Linux – Arch linux wifi funziona manualmente, come renderlo automatico?

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

Linux
  1. Come usare i comandi della cronologia di Bash

  2. Come inviare Stdout a più comandi?

  3. Come reindirizzare l'elenco dei comandi visualizzati da "scheda completa"?

  4. Come controllare HZ nel terminale?

  5. Come eseguire uno script .sh da qualsiasi percorso in un terminale?

Come visualizzare le immagini in miniatura nel terminale

Come registrare tutto ciò che fai nel terminale

Come aprire una finestra di un terminale Linux

Come aprire un PDF in un terminale Linux

Come utilizzare Terminale in cPanel?

Come eseguire più comandi Linux contemporaneamente nel terminale Linux