Často používám více než jeden terminál (nebo emulátor terminálu) najednou; a zatímco v X mohu kopírovat a vkládat příkazy, kromě toho, že to není příliš praktické, zjevně to nefunguje na skutečném TTY. První nápad, který mě napadá, je něco podobného:
command > /dev/sometty
Bohužel, command
je spuštěna před je to rourou a žádné triky jako echo `command`
bude fungovat bez ohledu na to, kolik podivných bash znaků ($
, `
, "
atd.) jsou tam. Takže /dev/sometty
prostě dostane nějaký text.
Problém je v tom, že někdy dokonce stojí za to, abych tyto příkazy vložil do souboru, udělal jej spustitelným atd., nebo krátce:vytvořil skript a spustil jej z příslušného terminálu. Ale to je hodně práce. Přemýšlel jsem o vytvoření skriptu pro vytvoření těchto souborů, pro instrukci:
termpipe -e "command1\ncommand2\"command 1 argument\\n(s)\"" -t /dev/sometty
udělalo by to něco jako:
- přepojte příkazy do, řekněme,
/tmp/termpipe-20140208-153029-1.sh
- udělejte soubor spustitelným
- spusťte soubor v příslušném terminálu
- po dokončení skript smažte
AFAIK, problém je v 3. :to neřeší žádný problém, protože bych potřeboval další termpipe
instanci spustit první na příslušném terminálu. A jeden pro toho. A další na to, ad infinitum . Takže to nemůže fungovat. Nebo může?…
Řešením by mohlo být použití pojmenovaného kanálu na terminál, a když se každý spustí, skript řekne kanálu, aby přeposlal vše, co obdrží, na terminál a pak to provedl (jako jakýsi démon ).
Myslím, že by to mohlo fungovat, ale nevím, jak nastavit počáteční skript. Jak mohu? Jak mohu říct FIFO, aby zadávalo pipetované příkazy pro spuštění příslušného terminálu? Bashe moc neznám, takže bych ocenil úplné vysvětlení.
Přijatá odpověď:
Po tomto můžete velmi dobře uskutečnit váš poslední plán. Aby příkaz, který má být odeslán, nebyl shellem zpracován, musí být ve formě řetězce, když dosáhne roury (tedy echo "command"
, nikoli echo `command`
). Poté jej musí přečíst proces na pozadí (podobně jako démon , ale ne nutně) spuštěna v příslušném terminálu. Mělo by být vyhodnoceno stejným procesem.
Ale je to kotel-ploché mít skript na potrubí. Pojďme tedy zobecnit vytvoření skriptu jako term-pipe-r.sh
(nezapomeňte chmod +x
to!):
#!/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
Řekněme, že chcete /dev/tty3
pro příjem příkazů:prostě jděte tam, udělejte
./term-pipe-r.sh tty3pipe & # $1 will be tty3pipe (in a new process)
A k odesílání příkazů z jakéhokoli terminálu (i od sebe samého):
echo "command" > tty3pipe
nebo tam spustit soubor:
cat some-script.sh > tty3pipe
Všimněte si, že toto potrubí ignoruje soubory jako .bashrc
a aliasy v nich obsažené, například alias ls='ls --color'
. Doufám, že to někomu pomůže.
Upravit (poznámka – výhoda nedémona ):
Výše jsem mluvil o tom, že čtečka rour není démon nutně, ale ve skutečnosti jsem zkontroloval rozdíly a ukázalo se, že v tomto případě je mnohem lepší být pouhým procesem na pozadí. Protože tímto způsobem, když zavřete terminál, EXIT
signál (SIGHUP
, SIGTERM
, nebo cokoli jiného) je také přijato skriptem a roura je poté smazána (viz řádek začínající trap
ve skriptu) automaticky, čímž se vyhnete zbytečnému procesu a souboru (a možná i dalším, pokud by takové přesměrování do zbytečné roury bylo).
Upravit (automatizace):
Přesto je nudné spouštět skript, který (alespoň já) pravděpodobně většinu času chcete. Tak to zautomatizujme! Měl by začínat v libovolném terminálu a jedna věc, kterou všechny čtou, je .bashrc
. Navíc je otravné používat ./term-pipe-r.sh
. Takže, jeden může udělat:
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)
Nyní k jeho spuštění budete potřebovat pouze tpr tty3pipe &
v /dev/tty3
kdykoli budete chtít. Ale proč to dělat, když to můžete nechat udělat automaticky? Toto by tedy mělo být přidáno do .bashrc
. Ale počkat:jak to bude znát název potrubí? Název může založit na TTY (které lze znát pomocí tty
příkaz), pomocí jednoduchých REGEX v sed
(a pár triků). Co byste měli přidat do ~/.bashrc
pak bude:
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