
Eu tenho um script Bash que estava tentando fazer para me ajudar a executar um comando bastante complexo com pequenas alterações que ele me perguntaria por meio de eco e leitura.
Encontrei soluções para forçá-lo a rodar um terminal para executar o comando, mas não estou interessado nisso. O que eu gostaria que ele fizesse é, se eu espaçar e apenas pressionar Enter no Nautilus (fazendo com que ele seja executado com Run Software), uma notificação aparecerá suavemente dizendo "Por favor, execute isso a partir de um terminal".
Consigo fazer com que o pop-up aconteça - já que conheço o comando - mas não consigo fazer com que o script Bash diga se está sendo executado dentro de um terminal ou não, parece que sempre penso assim. É mesmo possível?
Responder1
De man bash
baixoEXPRESSÕES CONDICIONAIS:
-t fd
True if file descriptor fd is open and refers to a terminal.
Supondo que fd 1 seja padrão, if [ -t 1 ]; then
deve funcionar para você. OGuia avançado de script de shellafirmações -t
usadas dessa maneira falharão ssh
e que o teste (usando stdin, não stdout) deve, portanto, ser:
if [[ -t 0 || -p /dev/stdin ]]
-p
testa se um arquivo existe e é um pipe nomeado. No entanto, eu observaria experimentalmente que isso não é verdade para mim: -p /dev/stdin
falha tanto para terminais normais quanto para sessões ssh, enquanto if [ -t 0 ]
(ou -t 1
) funciona em ambos os casos (veja também os comentários de Gilles abaixo sobre problemas nessa seção doGuia avançado de script de shell).
Se o problema principal for um contexto especializado a partir do qual você deseja chamar o script para se comportar de maneira apropriada a esse contexto, você pode evitar todos esses detalhes técnicos e evitar complicações usando um wrapper e uma variável personalizada:
!#/bin/bash
export SPECIAL_CONTEXT=1
/path/to/real/script.sh
Chame isso live_script.sh
ou qualquer outra coisa e clique duas vezes nele. É claro que você poderia realizar a mesma coisa com argumentos de linha de comando, mas um wrapper ainda seria necessário para fazer com que apontar e clicar em um navegador de arquivos GUI funcionasse.
Responder2
Use a variável bash $SHLVL para detectar o nível de aninhamento do shell. Em um script executado 'raw' clicando duas vezes será 1, em um script executado em um 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: $ não é necessário ao testar variáveis numéricas dentro de (( )).
Responder3
Embora a resposta de Cachinhos Dourados provavelmente esteja correta no caso típico, parece que existem casos extremos. No meu caso, meu xserver está configurado para inicializar tty1
e nunca sai desse tty. Se o Xorg stdout
for um TTY, parece que os clientes terão esse TTY vinculado ao seu descritor de arquivo por padrão.
Veja como resolvi meu 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
Não testei isso para ver se funciona em uma configuração X mais padrão e também duvido muito que este seja o único caso extremo. Se alguém encontrar uma solução de aplicação mais geral, volte e conte-nos.
Responder4
Outro, usando as opções do bash, defina a variável interna, $-
.
De .bashrc
,
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac