¿Cómo puede un script Bash saber cómo se ejecutó?

¿Cómo puede un script Bash saber cómo se ejecutó?

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 bashdebajoEXPRESIONES 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 ]; thendebería funcionar para usted. ElGuía avanzada de secuencias de comandos de ShellLas afirmaciones que -tse usan de esta manera fallarán sshy, por lo tanto, la prueba (usando stdin, no stdout) debería ser:

if [[ -t 0 || -p /dev/stdin ]]

-pprueba 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/stdinfalla 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.sho 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 tty1y nunca sale de ese tty. Si Xorg stdoutes 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

información relacionada