A menudo uso más de un terminal (o emulador de terminal) a la vez; y mientras que en X puedo copiar y pegar comandos, además de no ser muy práctico, obviamente no funciona en el TTY real. La primera idea que se me ocurre es algo parecido:
command > /dev/sometty
Desafortunadamente, el comando command
se ejecuta antes está canalizado, y no hay trucos como echo `command`
funcionará, sin importar cuántos caracteres bash raros ($
, `
, "
, etc.) están ahí. Así que /dev/sometty
simplemente recibe un mensaje de texto.
El problema es que, a veces, incluso vale la pena canalizar esos comandos en un archivo, hacerlo ejecutable, etc., o en breve:hacer un script y ejecutarlo desde la terminal adecuada. Pero eso es mucho trabajo. Estuve pensando en hacer un script para hacer estos archivos, para una instrucción:
termpipe -e "command1\ncommand2\"command 1 argument\\n(s)\"" -t /dev/sometty
haría algo como:
- enviar los comandos a, por ejemplo,
/tmp/termpipe-20140208-153029-1.sh
- hacer que el archivo sea ejecutable
- ejecutar el archivo en el terminal apropiado
- eliminar el script cuando termine de ejecutarse
AFAIK, el problema está en 3. :esto no resuelve ningún problema, ya que necesitaría otro termpipe
instancia para ejecutar la primera en el terminal apropiado. Y uno para ese. Y otra para eso, ad infinitum . Así que esto no puede funcionar. ¿O puede?…
La solución podría ser usar una canalización con nombre por terminal, y cuando cada una se inicia, un script le indicaría a la canalización que reenvíe cualquier cosa que reciba a la terminal y luego ejecutarla (como una especie de daemon ).
Creo que esto podría funcionar, pero no sé cómo configurar el script inicial. ¿Cómo puedo? ¿Cómo puedo decirle al FIFO que dé comandos canalizados para que se ejecute la terminal respectiva? No sé mucho de Bash, así que agradecería explicaciones completas.
Respuesta aceptada:
Después de esto, uno puede muy bien hacer que ese último plan suyo funcione. Para que el shell no procese el comando que se enviará, debe tener la forma de una cadena cuando llegue a la tubería (por lo tanto, echo "command"
, no echo `command`
). Luego tiene que ser leído por un proceso en segundo plano (como un daemon , pero no necesariamente) iniciado en el terminal apropiado. Debe ser evaluado por el mismo proceso.
Pero es boiler-platey tener un script por tubería. Así que generalicemos haciendo un script como term-pipe-r.sh
(no te olvides de chmod +x
eso!):
#!/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
Así que di que quieres /dev/tty3
para recibir comandos:solo ve allí, haz
./term-pipe-r.sh tty3pipe & # $1 will be tty3pipe (in a new process)
Y para enviar comandos, desde cualquier terminal (incluso de sí mismo):
echo "command" > tty3pipe
o para ejecutar un archivo allí:
cat some-script.sh > tty3pipe
Tenga en cuenta que esta tubería ignora archivos como .bashrc
, y los alias allí, como alias ls='ls --color'
. Espero que esto ayude a alguien.
Editar (nota:ventaja de no daemon ):
Arriba hablé de que el lector de tuberías no es un daemon necesariamente, pero de hecho, revisé las diferencias, y resulta que es mucho mejor ser un mero proceso en segundo plano en este caso. Porque de esta manera, cuando cierras la terminal, un EXIT
señal (SIGHUP
, SIGTERM
, o lo que sea) también es recibido por el script, y luego se elimina la canalización (consulte la línea que comienza con trap
en el script) automáticamente, evitando un proceso y un archivo inútiles (y tal vez otros si hubiera tal redireccionamiento a la tubería inútil).
Editar (automatización):
Aún así, es aburrido tener que ejecutar un script que (al menos yo) probablemente quiera la mayor parte del tiempo. Entonces, ¡automaticémoslo! Debería comenzar en cualquier terminal, y una cosa que todos leen es .bashrc
. Además, apesta tener que usar ./term-pipe-r.sh
. Entonces, uno puede hacer:
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)
Ahora, para ejecutarlo, solo necesitaría tpr tty3pipe &
en /dev/tty3
cuando quieras. Pero, ¿por qué hacer eso cuando puede hacerlo automáticamente? Entonces esto debería agregarse a .bashrc
. Pero espera:¿cómo sabrá el nombre de la tubería? Puede basar el nombre en el TTY (que se puede saber con el tty
comando), usando REGEX simples en sed
(y algunos trucos). Lo que debe agregar a ~/.bashrc
será entonces:
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