
Tengo un script Bash que estaba intentando crear para ayudarme a ejecutar un comando bastante complejo con pequeños cambios sobre los que me preguntaría mediante eco y lectura.
He encontrado soluciones para obligarlo a ejecutar una terminal para ejecutar el comando, pero eso no me interesa. Lo que me gustaría que hiciera es que, si me espacio y simplemente presiono Enter en Nautilus (haciendo que se ejecute con Ejecutar software), aparecerá suavemente una notificación que dice "Ejecute esto desde una terminal".
Puedo hacer que aparezca la ventana emergente, ya que conozco el comando, pero no puedo hacer que el script Bash sepa si se está ejecutando dentro de una terminal o no, parece que siempre es así. ¿Es siquiera posible?
Respuesta1
Por man bash
debajoEXPRESIONES CONDICIONALES:
-t fd
True if file descriptor fd is open and refers to a terminal.
Suponiendo que fd 1 sea estándar, if [ -t 1 ]; then
debería funcionar para usted. ElGuía avanzada de secuencias de comandos de ShellLas afirmaciones que -t
se usan de esta manera fallarán ssh
y, por lo tanto, la prueba (usando stdin, no stdout) debería ser:
if [[ -t 0 || -p /dev/stdin ]]
-p
prueba si un archivo existe y es una canalización con nombre. Sin embargo, Notaría por experiencia que esto no es cierto para mí: -p /dev/stdin
falla tanto en terminales normales como en sesiones ssh, mientras que if [ -t 0 ]
(o -t 1
) funciona en ambos casos (consulte también los comentarios de Gilles a continuación sobre problemas en esa sección delGuía avanzada de secuencias de comandos de Shell).
Si el problema principal es un contexto especializado desde el cual desea llamar al script para que se comporte de una manera apropiada para ese contexto, puede evitar todos estos tecnicismos y ahorrarse algunos problemas usando un contenedor y una variable personalizada:
!#/bin/bash
export SPECIAL_CONTEXT=1
/path/to/real/script.sh
Llame a esto live_script.sh
o lo que sea y haga doble clic en eso. Por supuesto, podría lograr lo mismo con argumentos de línea de comando, pero aún sería necesario un contenedor para hacer que apuntar y hacer clic en un explorador de archivos GUI funcione.
Respuesta2
Utilice la variable bash $SHLVL para detectar el nivel de anidamiento del shell. En un script ejecutado 'sin formato' al hacer doble clic, será 1, en un script que se ejecuta dentro de una terminal será 2.
#!/bin/bash
if (( SHLVL < 2 )) ; then
echo "Please run this from a terminal."
read -p "Press <Enter> to close this window"
exit 1
fi
# rest of script
Nota: No se requiere $ cuando se prueban variables numéricas dentro de (( )).
Respuesta3
Aunque la respuesta de Ricitos de Oro probablemente sea correcta en el caso típico, parece que hay casos extremos. En mi caso, mi servidor x está configurado para iniciarse tty1
y nunca sale de ese tty. Si Xorg stdout
es un TTY, entonces parece que los clientes tendrán ese TTY vinculado a su descriptor de archivo de forma predeterminada.
Así es como resolví mi problema:
#!/bin/bash
isxclient=$( readlink /dev/fd/2 | grep -q 'tty' && [[ -n $DISPLAY ]] ; echo $? )
if [[ ! -t 2 || $isxclient == "0" ]]; then
notify-send "Script wasn't started from an interactive shell"
else
echo "Script was started from an interactive shell"
fi
No he probado esto para ver si funciona en una configuración X más estándar, y también dudo mucho que este sea el único caso extremo. Si alguien encuentra una solución más aplicable en general, regrese y díganoslo.
Respuesta4
Otro, usando las opciones de bash establece la variable interna, $-
.
De .bashrc
,
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac