
Ich habe versucht, ein Bash-Skript zu erstellen, das mir dabei helfen sollte, einen ziemlich komplexen Befehl mit kleinen Änderungen auszuführen, zu denen ich per Echo und Lesen aufgefordert werde.
Ich habe Lösungen gefunden, um es zu zwingen, ein Terminal auszuführen, um den Befehl auszuführen, aber daran bin ich nicht interessiert. Ich möchte, dass es, wenn ich es ausschalte und in Nautilus einfach die Eingabetaste drücke (damit es mit „Software ausführen“ läuft), einfach sanft eine Benachrichtigung anzeigt, die besagt: „Bitte führen Sie dies von einem Terminal aus aus.“
Ich kann das Popup aufrufen – ich kenne den Befehl –, aber ich kann das Bash-Skript nicht dazu bringen, zu erkennen, ob es in einem Terminal ausgeführt wird oder nicht. Es scheint immer so zu denken. Ist das überhaupt möglich?
Antwort1
Von man bash
unterBEDINGTE AUSDRÜCKE:
-t fd
True if file descriptor fd is open and refers to a terminal.
Vorausgesetzt, fd 1 ist der Standardausgang, if [ -t 1 ]; then
sollte es für Sie funktionieren.Erweitertes Shell-Scripting-Handbuchbehauptet, dass -t
bei Verwendung dieser Methode ein Failover auftritt ssh
und dass der Test (unter Verwendung von stdin, nicht stdout) daher wie folgt lauten sollte:
if [[ -t 0 || -p /dev/stdin ]]
-p
testet, ob eine Datei vorhanden ist und ob es sich um eine benannte Pipe handelt. Jedoch, ich möchte anmerken, dass dies erfahrungsgemäß für mich nicht zutrifft: -p /dev/stdin
schlägt sowohl bei normalen Terminals als auch bei SSH-Sitzungen fehl, während if [ -t 0 ]
(oder -t 1
) in beiden Fällen funktioniert (siehe auch Gilles Kommentare weiter unten zu Problemen in diesem Abschnitt desErweitertes Shell-Scripting-Handbuch).
Wenn das Hauptproblem ein spezieller Kontext ist, aus dem Sie das Skript aufrufen möchten, damit es sich in einer für diesen Kontext angemessenen Weise verhält, können Sie alle diese Formalitäten umgehen und sich einiges an Aufwand ersparen, indem Sie einen Wrapper und eine benutzerdefinierte Variable verwenden:
!#/bin/bash
export SPECIAL_CONTEXT=1
/path/to/real/script.sh
Rufen Sie dies live_script.sh
oder was auch immer auf und doppelklicken Sie stattdessen darauf. Sie könnten dasselbe natürlich auch mit Befehlszeilenargumenten erreichen, aber Sie würden trotzdem einen Wrapper benötigen, damit Point-and-Click in einem GUI-Dateibrowser funktioniert.
Antwort2
Verwenden Sie die Bash-Variable $SHLVL, um den Verschachtelungsgrad der Shell zu ermitteln. In einem Skript, das „raw“ durch Doppelklicken ausgeführt wird, ist es 1, in einem Skript, das in einem Terminal ausgeführt wird, ist es 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
Hinweis: Beim Testen numerischer Variablen innerhalb von (( )) ist $ nicht erforderlich.
Antwort3
Obwohl die Antwort von Goldilocks im Normalfall wahrscheinlich richtig ist, scheint es doch Sonderfälle zu geben. In meinem Fall ist mein XServer so konfiguriert, dass er von tty1
diesem TTY startet und es nie verlässt. Wenn es sich bei Xorg stdout
um ein TTY handelt, scheint es, dass die Clients dieses TTY standardmäßig mit ihrem Dateideskriptor verknüpft haben.
So habe ich mein Problem gelöst:
#!/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
Ich habe nicht getestet, ob es auf einer standardmäßigeren X-Konfiguration funktioniert, und ich bezweifle auch sehr, dass dies der einzige Sonderfall ist. Wenn jemand eine allgemeiner anwendbare Lösung findet, kommen Sie bitte zurück und teilen Sie es uns mit.
Antwort4
Eine andere Möglichkeit besteht darin, mithilfe der Bash-Optionen interne Variablen festzulegen $-
.
Aus .bashrc
,
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac