Ich habe Fedora 20 und Gnome3 Classic und versuche, die CTRL/ALT/Fn-Terminalfenster zu verwenden. Wenn ich eine Datei mit Emacs bearbeiten möchte, verwende ich das folgende Skript, damit meine Hints-Datei automatisch angezeigt wird und Emacs als Hintergrundjob ausgeführt wird. Dies funktioniert im Nicht-Login-Terminal von Gnome-Desktopanwendungen aus einwandfrei, aber im Login-Terminal erhalte ich Fehlermeldungen: (erhalten durch Umleitung mit „&> e“ im CTL/ALT/F2-Fenster)
home/Harry/bin/emx: line 4: t: Permission denied
+---------------------------------------------------+
| EmacsHints.txt found and displayed |
| Usage: ./emx <filename> .. |
| .. Opens EmacsHints.txt and <filename> in emacs |
+---------------------------------------------------+
emacs: standard input is not a tty
Kann mir das bitte jemand erklären und mir sagen, wie ich es vermeiden und das (zweifellos modifizierte) EMX-Skript sowohl in Terminals mit als auch ohne Anmeldung erfolgreich verwenden kann?
Überarbeitete Version meines EMX-Skripts, ich habe meine Notizen und Debugging-Materialien beigefügt:
#!/bin/sh
emxhn="EmacsHints.txt"
emxhf="/home/Harry/emacs/$emxhn"
ps aux | grep $emxhn > t
T=`wc -l t` # no spaces allowed between T and = and value
# echo $T
wc -l t > t1
T=`awk '$1' t1`
# echo $T
echo "+---------------------------------------------------+"
# In the test "" needed round $T else it is split into two commands ..
# .. so are the spaces after [ and before ]
# could be if ( [...] ) then or if [...] ; then
if [ "$T" = "2 t" ]; then
# echo "+----------------------------------------------+"
echo "| $emxhn already present"\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "|"
else
emacs $emxhf &
echo "| $emxhn found and displayed"\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "|"
fi
if [ "$#" = "1" ]; then
emacs $1 &
else
echo "| Usage: ./emx <filename> .." \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "|"
echo "|" \ ".. Opens $emxhn and <filename> in emacs" "|"
fi
echo "+---------------------------------------------------+"
Ja, ich sehe, ich bin in die XY-Falle getappt und habe X gefragt, obwohl ich Y hätte fragen sollen, also hier ist Y
Ich verwende Emacs häufig, aber nicht ständig, und ich habe auch eine Datei mit Hinweisen, in der ich festhalte, wie ich die anfallenden Aufgaben erledige. Ich möchte diese Hinweise gerne zur Verfügung haben, während ich Emacs verwende. Ich habe versucht, dies zu automatisieren, sodass die Datei immer dann geöffnet wird, wenn ich Emacs starte und die Hinweise noch nicht vorhanden sind. Dieses Skript war mein Versuch, dies zu tun, und es hat funktioniert, während ich Emacs von einem Nicht-Anmeldeterminal innerhalb meiner klassischen Gnome3-GUI ausgeführt habe. Der Versuch in einem Anmeldeterminal mit CTL/ALT/F2 ergab die zitierten Fehlermeldungen.
Ich verwende und liebe Unix und Fedora Linux seit vielen Jahren, aber es gibt offensichtlich noch eine ganze Menge mehr zu lernen.
Antwort1
Im Folgenden analysiere ich Ihr Skript. Aber nachdem ich das getan habe, denke ich, die Antwort auf dieFrage, die Sie hätten stellen sollenIst:
- Führen Sie es
emacs --daemon
von Ihrem.profile
aus. Dadurch wird eine Hintergrundinstanz von Emacs erstellt. - Ausführen
emacsclient FILENAME
, um eine Datei in Emacs zu öffnen. Dadurch wird ein neues Fenster erstellt (entweder ein X11-Fenster oder ein Fenster, das das aktuelle Terminal verwendet). - Laden Sie die
EmacsHints
Datei in Ihre Emacs-Startdatei: Fügen Sie sie(find-file "/home/Harry/emacs/EmacsHints.txt")
in Ihre ein.emacs
.
Wir können nicht mit Sicherheit sagen, warum Sie erhalten t: Permission denied
, da Sie das Skript, das diesen Fehler erzeugt hat, nicht gepostet haben (das von Ihnen gepostete Skript hat einen Kommentar in Zeile 4). Aber Sie erstellen eine temporäre Datei im aktuellen Verzeichnis; das ist unter allen Umständen eine schlechte Idee und funktioniert wahrscheinlich nicht, wenn Sie keine Schreibberechtigung für das aktuelle Verzeichnis haben.
Wenn Sie eine temporäre Datei erstellen müssen, verwenden Siemktemp
. Allerdings stellen temporäre Dateien hier eine unnötige Komplikation dar: Verwenden Sie Befehlsersetzung, um die Ausgabe der Befehle in einer Variablen zu speichern.
#!/bin/sh
ps_lines=$(ps aux | grep EmacsHints)
line_count=$(echo "$ps_lines" | wc -l)
T=$(echo "$line_count" | awk '$1')
if [ "$T" = "2" ]; then …
Dies alles wiederum ist furchtbar kompliziert – leiten Sie die Ausgabe von einfach grep
in weiter wc
, und der awk-Schritt bewirkt nichts Nützliches.
if [ "$(ps aux | grep EmacsHints | wc -l)" = 2 ]; then …
Darüber hinaus ist Ihr Test unzuverlässig: Wenn die EmacsHints
Datei geöffnet ist, ps
wird manchmal eine Zeile mit zurückgegeben EmacsHints
, manchmal zwei: Dies hängt vom Timing der Prozesse ps
und ab grep
. Anstatt Ihren eigenen Test zu erstellen (was nicht funktioniert), verwenden Sie Tools, die speziell für diesen Zweck entwickelt wurden:pidof
oderpgrep
.
#!/bin/sh
if pgrep -f 'EmacsHints\.txt' >/dev/null; then …
Voilà! Einfacher, und es funktioniert tatsächlich.
Nun, esmeistensfunktioniert. Wenn Sie die EmacsHints
Datei in Emacs öffnen, ohne sie in der Befehlszeile anzugeben, wird dies nicht erkannt. Ich würde eine bessere Lösung anbieten, aber ich verstehe nicht, was Sie erreichen möchten. Wenn Sie die EmacsHints
Datei immer in Emacs geöffnet haben möchten, öffnen Sie sie von Ihrem .emacs
.
Emacs startet etwas langsam, aber viele Benutzer (mich eingeschlossen) richten es so ein, dass es nach der Anmeldung ausgeführt wird und dann nicht mehr beendet wird. Führen Sie es emacs --daemon
von Ihrem .profile
aus aus. Um eine Datei in der vorhandenen Emacs-Instanz zu öffnen, rufen Sie auf emacsclient
.
Bezüglich „Standardeingabe ist kein TTY“ können Sie Emacs nur dann im Hintergrund laufen lassen, wenn es ein GUI-Fenster öffnet. Wenn Sie Emacs im Terminal laufen lassen, muss es im Vordergrund sein, sonst kann es nicht auf das Terminal zugreifen. Wenn Sie Emacs nur unter X im Hintergrund laufen lassen wollen:
if [ -n "$DISPLAY" ]; then
emacs "$1" &
else
emacs "$1"
fi
Übrigens sollten Sie in einem Shell-Skript Variablen- und Befehlsersetzungen immer in Anführungszeichen setzen: "$1"
, "$foo"
, "$(somecommand)"
, usw. Wenn die Ersetzung nicht in Anführungszeichen steht, wird der Wert nicht als Zeichenfolge, sondern als Liste von Glob-Mustern interpretiert. Dieses Problem tritt normalerweise bei Skripten auf, die bei Dateinamen mit Leerzeichen fehlschlagen. Wenn Sie nicht verstehen, was das alles bedeutet, verwenden Sie einfach Anführungszeichen.
Oder Sie verwenden einfach emacsclient
.
Antwort2
Zu dieser Nachricht:
emx: line 4: t: permission denied
Die erste besteht darin, Ihnen mitzuteilen, dass Ihr Befehl:
ps aux | grep EmacsHints > t
hat keine Berechtigung, die Datei t
in das Verzeichnis zu schreiben, in dem sie sich beim Ausführen befindet. Es ist besser, einen vollständigen Pfad anzugeben. Ich würde /tmp/t
Folgendes vorschlagen:
ps aux | grep EmacsHints > /tmp/t
Die andere Nachricht:
emacs: standard input is not a tty
Sagt Ihnen, dass das Skript keinen Zugriff auf ein TTY hat, um Emacs anzuzeigen. Um ein Tool wie emacs
oder vim
auf diese Weise auszuführen, müssen Sie häufig Zugriff auf ein TTY-Gerät haben, damit Sie auf dessen STDIN und STDOUT zugreifen können.
Wenn Sie verzweifelt sind oder das Fehlen von STDIN/STDOUT Ihnen egal ist, können Sie in Ihrem Skript wie folgt ein neues erstellen:
emacs < $(tty) > $(tty)
Es gibt andere Methoden, damit umzugehen, siehe diese SO-Fragen und -Antworten mit dem Titel:Wie starte ich einen Editor aus einem Shell-Skript?.