Ein Shell-Skript unter OS X ausführen, ohne dass ein Terminalfenster angezeigt wird?


23

Ich versuche, ein paar Tastaturkürzel einzurichten, mit denen bestimmte iTerm-Sitzungen geöffnet werden können, die ich mit BetterTouchTool und ein bisschen AppleScript-Magie ausführen konnte. Das Problem ist, dass OS X darauf besteht, ein Terminal-Fenster für jedes Shell-Skript zu öffnen, das Sie über die GUI ausführen (z. B. über Finder oder als Tastenkürzel von BetterTouchTool). Das Terminalfenster wird nicht angezeigt, wenn ich das Skript direkt von einem anderen Terminal aus starte.

Eine Problemumgehung bestand darin, das Skript in ein .app-Verzeichnis zu packen, wodurch das Problem des überflüssigen Terminalfensters behoben wird, aber einige andere Probleme auftreten (z. B. scheint OS X jedes resultierende iTerm-Fenster als separate App zu behandeln und mein Dock zu überfrachten ). (BEARBEITEN: Dieses Verhalten wurde tatsächlich durch einen Fehler in meinem Skript verursacht, siehe unten)

Ich habe auch versucht, die Terminal-App einem anderen virtuellen Desktop in den Spaces-Einstellungen zuzuweisen, um sie außer Sichtweite zu bringen. Dann wird sie jedoch erst auf diesen Desktop umgeschaltet, bevor das Skript ausgeführt wird.

Gibt es eine Möglichkeit, dieses Verhalten vollständig zu deaktivieren? Ich habe bereits die Einstellung in den Terminal-Einstellungen gefunden, um das Fenster zu schließen, nachdem das Skript beendet wurde, aber es ist immer noch ärgerlich, wenn das Terminal-Fenster für eine Sekunde angezeigt wird.


Entschuldigung, ich verstehe nicht ganz. Was möchten Sie mit diesen Shell-Skripten machen? Möchten Sie iTerm über ein Shell-Skript öffnen? Sprechen Sie in Ihrer Frage ausschließlich über Terminal.app oder mischen Sie iTerm mit "Terminal"? Könnten Sie vielleicht ein Beispiel für das posten, was Sie ausführen möchten?
Slhck

Ich habe mehrere iTerm-Sitzungen eingerichtet, um eine normale Shell zu starten, eine Rails-Konsole zu öffnen, das Rails-Protokoll anzuzeigen usw. Ich verwende ausschließlich iTerm, und das Terminal wird aus irgendeinem dummen Grund automatisch von OS X geöffnet. Trotzdem habe ich eine Lösung gefunden, mit der der Bundle-Ansatz ordnungsgemäß funktioniert (siehe bearbeitete Frage).
Toupeira

Aha! Nun, es wäre fantastisch, wenn Sie Ihre eigene Frage beantworten könnten (mit dem Button unten) und uns mitteilen könnten, was Sie getan haben oder wie Sie das Problem gelöst haben. Posten Sie vielleicht einige Beispiele in Ihrer Frage und fügen Sie dann einfach eine kurze Antwort hinzu. Auf diese Weise kann jemand, der über Ihren Beitrag stolpert, etwas daraus lernen!
Slhck

Nun, ich habe immer noch keine Antwort auf die eigentliche Frage (dh wie man das Terminal komplett umgeht, ohne einen .app-Wrapper verwenden zu müssen), also lasse ich es lieber offen, falls mich jemand aufklären kann.
Toupeira

1
Ich bin immer noch verwirrt. Sie nicht wollen , dass sie über eine .app von Automator erstellt laufen?
Slhck

Antworten:


21

Öffnen Sie Automator , wählen Sie " Anwendung" , fügen Sie eine Aktion " Shell-Skript ausführen" hinzu und fügen Sie Ihren Shell-Befehl in Anführungszeichen ein (wenn Sie eine Datei haben, können Sie sie einfach per Drag & Drop verschieben).

Jetzt können Sie es nicht mehr abspielen, sondern überall als App speichern und sogar das Symbol festlegen .


Ich habe versucht, einen Befehl auf diese Weise über eine Vollbild-App auszuführen, er wurde jedoch immer im Hintergrund geöffnet. Ich musste den Befehl in der Shell blockierungsfrei hinterlegen, indem ich a anhängte &und dann ein AppleScript aufrief, um die App (in meinem Fall mplayer) nach vorne zu bringen: mplayer myvideo.avi &; osascript -e 'tell application "System Events" to set frontmost of the first process whose displayed name is "mplayer" to true'
Lenar Hoyt

Cooler Hack @mcb. Aber ich verstehe nicht warum. Normalerweise möchten wir das Terminalfenster ausblenden, da es ein anderes Fenster öffnet, nämlich das Hauptfenster. Wenn Sie das erste Terminal-Fenster von mplayer benötigen, wird vermutlich kein anderes geöffnet, und warum sollten Sie es dann zunächst ausblenden?
Cregox

Ich verwende mplayer, um ein Video aus einer Diashow (in Skim) abzuspielen. Es gibt einen Fehler, bei dem der Player im Hintergrund bleibt, wenn Skim auf Vollbild eingestellt ist. Ich bin mir jedoch nicht sicher, ob dieser Fehler nur mit Skim oder allen Vollbild-Apps zusammenhängt. Daher habe ich mir vorgenommen, meine Lösung hier zu veröffentlichen.
Lenar Hoyt

6

Hier ist ein schnelles und schmutziges Beispiel ohne großen Aufwand (für eine App namens "myapp"):

  1. Erstellen Sie eine partielle Anwendungshierarchie:

        mkdir -p ./myapp.app/Contents/MacOS
    
  2. Stellen Sie sicher, dass die erste Zeile Ihres Skripts den vollständigen Pfad zum gewünschten Programm enthält, z.

    #!/bin/bash
    
  3. Nennen Sie Ihr Shell-Skript "myapp" (keine Anführungszeichen, keine Erweiterung), geben Sie ihm Ausführungsberechtigungen und legen Sie es dann im MacOS-Unterverzeichnis ab. So erteilen Sie ihm Ausführungsberechtigungen:

    chmod ugo+x myapp
    
  4. Wechseln Sie in das Inhaltsverzeichnis und erstellen Sie eine PkgInfo-Datei mit der Zeichenfolge: APPL ???? [kein Zeilenendezeichen am Ende der Zeichenfolge!] Verwenden Sie das Dienstprogramm cat (1), um die Datei zu erstellen:

    cat > PkgInfo
    APPL????
    

    Nachdem Sie den String eingegeben haben (drücken Sie nicht die Eingabetaste!), Geben Sie zwei Strg-Ds ein, um
    die Datei ohne Zeilenabschluss zu schließen und zur Shell-Eingabeaufforderung zurückzukehren.

  5. Doppelklicken Sie im Finder auf Ihre neue "App". Es wird ohne Fenster ausgeführt.


Funktionierte nicht unter 10.13.6, Fehlermeldung "Sie können die Anwendung" LoginSessionTimeLimit.app "nicht öffnen, da sie auf diesem Mac-Typ nicht unterstützt wird."
Douglas Held

1
Hat für mich in Mojave (10.14.3) gearbeitet. Ich mochte diesen Ansatz wirklich. Vielen Dank.
loco.loop

Arbeitete für mich am 13.10.6. @Douglas Held versuchen Sie, Ihr Skript "manuell", dh vom Terminal aus auszuführen. Wahrscheinlich wird es mit Fehler beendet, daher funktioniert es nicht für Sie ...
marekful

Groß! Getestet in Mojave 10.14.6
Nicola Mingotti


3

Hier ist eine kleine Problemumgehung, falls Sie Lust auf Anwendungsstarter wie Alfred haben . Ich benutze es jeden Tag und habe mir das Powerpack gekauft , mit dem Sie Silent-Shell-Skripte ausführen können .

Bildbeschreibung hier eingeben

Diese öffnen beim Ausführen kein Terminal und können an eine beliebige Schlüsselwortsequenz gebunden werden. Sie können sogar Parameter enthalten und zusätzliche Optionen haben:

Bildbeschreibung hier eingeben

Ich benutze dies für einige kleine Schnipsel und es ist sehr flexibel.


Dies ist unter Alfred 2 nicht mehr verfügbar. Erstellen Sie stattdessen ein "Run Script", wie im Bild gezeigt .
Dave Newton

1

Wenn Sie einen Schlüssel hinzufügen LSUIElementund 1in Info.plistIhrer App festlegen , wird im Dock kein Symbol erstellt.

Hier ist Info.plistmeine kleine Shell-Skript-App:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleExecutable</key>
    <string>launch</string>
    <key>CFBundleIconFile</key>
    <string>launch</string>
    <key>LSUIElement</key>
    <string>1</string>
</dict>
</plist>

Danke, aber das scheint keine Wirkung zu haben. Ich habe auch versucht, touchdas Bundle zu installieren, um sicherzustellen, dass die neueste Version verwendet wurde.
Trotzdem

Für mich hat Touch auch nicht geholfen (ich habe versucht, LSUIElement auszuschalten), es gibt eine andere Art von Caching, aber das Komprimieren und Extrahieren von Anwendungen hat geholfen. Warum magst du nicht Bundle-Ansatz? Sie können auch applescript verwenden und einfach ausführen. Dadurch do shell script "say 'arsti'"wird das Terminalfenster nicht geöffnet.
TIG

Okay, es stellt sich heraus, dass ich nur ein Idiot bin ;-) Ich konnte nicht zuverlässig prüfen, ob eine App bereits mit AppleScript ausgeführt wird. Daher habe ich ein normales Bash-Skript verwendet, das aufruft pgrepund dann den entsprechenden Code direkt an weiterleitet osascript(der AppleScript-Interpreter). Das Problem ist, dass pgrepes von Homebrew stammt und nicht in der Standardeinstellung enthalten ist $PATH. Daher hat mein Skript immer eine neue iTerm-Instanz gestartet, auch wenn sie bereits ausgeführt wurde. Nach dem Hinzufügen des vollständigen Pfads zum pgrepSkript scheint der Bundle-Ansatz doch noch in Ordnung zu sein, daher denke ich, dass ich jetzt glücklich bin
;-)

Kombiniert man diese Antwort mit der von @JeffB oben und mit einer vereinfachten Version von @tigs Info.plist (ich habe die Tasten CFBundleExecutableund entfernt CFBundleIconFile), funktioniert dies perfekt.
Dave Land

0

Hier ist ein Workaround:

Kompilieren Sie ein AppleScript, das ein Shell-Skript aufruft :)

osacompile -e 'do shell script "cd ~; echo aaa > temp.txt"' -o ~/name_of_script.scpt

Das osacompilewird das 'do shell script "XXX"'Applescript-Snippet kompilieren . Ihr Shell-Skript ist das XXX.

Achten Sie beim Zitieren darauf, dass das Shell-Skript korrekt zitiert wird, damit die Shell, mit der Sie es kompilieren, noch intakt ist.

Dies kann jedoch von BetterTouchTool aus ohne Umstände ausgeführt werden.


0

Es gibt noch ein anderes mögliches Training. Sichern Sie Ihr Shell-Skript in einem Automator-Workflow. Rufen Sie den Workflow mit launchd auf. Der Code lautet:

/usr/bin/automator /path/to/the/file.workflow

Dies startet kein Programm und wird auch nicht in der Menüleiste angezeigt und ist daher leiser als eine Platypus-App.

Ein noch besserer Weg, Shell-Skripte auszuführen, ist direkt in launchd.

/bin/bash /path/to/shellScript.command

Führt den Befehl im Hintergrund aus.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.