¿Ejecutar un script de shell en OS X sin que aparezca una ventana de terminal?


23

Estoy tratando de configurar algunos atajos de teclado que abren sesiones específicas de iTerm, lo que pude hacer con BetterTouchTool y un poco de magia AppleScript. El problema es que OS X insiste en abrir una ventana de Terminal para cualquier script de shell que ejecute a través de la GUI (es decir, desde Finder, o como un atajo de teclado desde BetterTouchTool). La ventana de terminal no aparece si ejecuto el script directamente desde otro terminal.

Una solución alternativa que encontré fue envolver el script en un directorio .app, que resuelve el problema de la ventana de terminal superflua, pero tiene otros problemas (por ejemplo, OS X parece tratar cada ventana iTerm resultante como una aplicación separada, abarrotando mi base) ) (EDITAR: este comportamiento en realidad fue causado por un error en mi script, ver más abajo)

También intenté asignar la aplicación Terminal a otro escritorio virtual en la configuración de Espacios en un intento de moverlo fuera de la vista, pero luego solo cambiará a ese escritorio antes de ejecutar el script.

¿Hay alguna manera de deshabilitar este comportamiento por completo? Ya encontré la configuración en las preferencias de Terminal para cerrar la ventana después de que el script haya terminado, pero sigue siendo molesto que aparezca la ventana de Terminal por un segundo.


Lo siento, no entiendo del todo. ¿Qué quieres hacer con esos scripts de shell? ¿Desea abrir iTerm a través de un script de shell? ¿Está hablando exclusivamente de Terminal.app o mezclando iTerm con "Terminal" en su pregunta? ¿Podría publicar un ejemplo de lo que está tratando de ejecutar?
slhck

He configurado varias sesiones de iTerm para iniciar un shell normal, abrir una consola de Rails, mostrar el registro de Rails, etc. Estoy usando iTerm exclusivamente, y OS X abre automáticamente la Terminal por cualquier razón tonta. Pero de todos modos, encontré una solución para hacer que el enfoque de paquete funcione correctamente (ver pregunta editada).
toupeira

¡Veo! Bueno, sería increíble si pudieras responder tu propia pregunta (usando el botón a continuación) y contarnos qué hiciste o cómo resolviste el problema. Tal vez publique algunos ejemplos en su pregunta y luego simplemente agregue una breve respuesta. De esta manera, si alguien se topa con tu publicación, ¡podría aprender algo de ella!
slhck

Bueno, todavía no tengo una respuesta para la pregunta real (es decir, cómo evitar la Terminal por completo, sin tener que usar un envoltorio .app), así que prefiero dejarla abierta en caso de que alguien pueda iluminarme.
toupeira

1
Todavía estoy confundido. Usted no desea ejecutar ellos a través de un .app creado por Automator?
slhck

Respuestas:


21

Abra Automator , elija Aplicación , agregue una acción Ejecutar script de Shell y coloque su comando Shell entre comillas (si tiene un archivo, simplemente puede arrastrarlo y soltarlo).

Además de reproducirlo, ahora puede guardarlo (como una aplicación en cualquier lugar) e incluso configurar el icono .


Traté de ejecutar un comando de esta manera desde una aplicación de pantalla completa, sin embargo, siempre lo abrió en segundo plano. Tuve que poner en segundo plano el comando en el shell de manera no bloqueante agregando un &y luego llamar a un AppleScript para llevar la aplicación (en mi caso mplayer) al frente: 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

Cool hack @mcb. Pero no entiendo por qué. Por lo general, queremos ocultar la ventana del terminal porque abrirá otra ventana, que es la principal. Si necesita la primera ventana de terminal de mplayer, supongo que no abre otra y entonces ¿por qué querría ocultarla en primer lugar?
cregox

Estoy usando mplayerpara reproducir un video desde una presentación de diapositivas (en Skim). Hay un error que el jugador permanece en segundo plano si Skim está configurado para pantalla completa, sin embargo, no estoy seguro de si este error solo está relacionado con Skim o con todas las aplicaciones de pantalla completa, así que pensé que publicaría mi solución aquí.
Lenar Hoyt

6

Aquí hay un ejemplo rápido y sucio casi sin esfuerzo (para una aplicación llamada "myapp"):

  1. Haga una jerarquía parcial de aplicaciones:

        mkdir -p ./myapp.app/Contents/MacOS
    
  2. Asegúrese de que la primera línea de su script tenga la ruta completa al programa necesario, por ejemplo,

    #!/bin/bash
    
  3. Nombre su script de shell "myapp" (sin comillas, sin extensión), dele permisos de ejecución y luego póngalo en el subdirectorio MacOS. Para darle permisos de ejecución:

    chmod ugo+x myapp
    
  4. Vaya al subdirectorio Contenido y cree un archivo PkgInfo que contenga la cadena: APPL ???? [¡sin terminador de línea al final de la cadena!] Use la utilidad cat (1) para crear el archivo:

    cat > PkgInfo
    APPL????
    

    Después de haber escrito la cadena (¡no presione la tecla de retorno!), Ingrese dos control-D, que cerrarán
    el archivo sin terminador de línea y lo regresarán al indicador de comandos de la shell).

  5. Haga doble clic en su nueva "aplicación" desde el buscador. Se ejecutará sin ventana.


No funcionó en 10.13.6, el mensaje de error dice "No puede abrir la aplicación" LoginSessionTimeLimit.app "porque no es compatible con este tipo de Mac".
Douglas celebrada el

1
Trabajó en Mojave (10.14.3) para mí. Realmente me gustó este enfoque. Gracias.
loco.loop

Trabajó para mí el 10.13.6. @ Douglas Held intente ejecutar su script "manualmente", es decir, desde la Terminal. Probablemente sale con error, por lo tanto, no está funcionando para usted ...
marekful

¡Excelente! Probado trabajando en Mojave 10.14.6
Nicola Mingotti

4

Es posible que desee consultar Platypus , que crea aplicaciones Mac OS X a partir de scripts de shell y otros scripts interpretados.


3

Aquí hay una pequeña solución, en caso de que te gusten los lanzadores de aplicaciones como Alfred . Lo uso todos los días y compré el Powerpack , que le permite ejecutar scripts de shell silenciosos.

ingrese la descripción de la imagen aquí

Estos no abrirán una terminal cuando se ejecuten y pueden vincularse a cualquier secuencia de palabras clave. Incluso pueden incluir parámetros y tienen opciones adicionales:

ingrese la descripción de la imagen aquí

Lo uso para algunos fragmentos pequeños, y es muy flexible.



1

Si agrega una clave LSUIElementy la configura 1enInfo.plist su aplicación, no creará un ícono en Dock.

Aquí está Info.plistmi pequeña aplicación de script de shell:

<?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>

Gracias, pero esto no parece tener un efecto. También probé touchel paquete para asegurarme de que se utilizara la versión más nueva. Pero de todos modos, no me gusta mucho el enfoque de paquete porque parece que siempre creará instancias de aplicaciones separadas
toupeira

Para mí, el tacto tampoco ayudó (intenté desactivar LSUIElement), hay otro tipo de almacenamiento en caché, pero la aplicación de compresión y extracción ayudó. ¿Por qué no te gusta el enfoque de paquete? También puede usar AppleScript y simplemente ejecutar do shell script "say 'arsti'", esto no abrirá la ventana de terminal.
tig

Bien, resulta que soy solo un idiota ;-) No pude encontrar una manera confiable de verificar si una aplicación ya se está ejecutando con AppleScript, así que utilicé un script bash normal que llama pgrep, y luego pasa el código relevante directamente a osascript(el intérprete de AppleScript). El problema es que pgrepvino de Homebrew y no está en el valor predeterminado $PATH. Entonces, mi script siempre lanzó una nueva instancia de iTerm, incluso si ya se estaba ejecutando. Después de agregar el camino completo pgrepen el script, el enfoque de paquete parece funcionar bien después de todo, así que creo que estoy feliz por ahora ;-)
toupeira

Combinando esta respuesta con la de @JeffB anterior, y con una versión simplificada de Info.plist de @ tig (eliminé las teclas CFBundleExecutabley CFBundleIconFile), conseguí que funcionara perfectamente.
Dave Land

0

Aquí hay una pequeña solución:

Compile un applecript que llame a un script de shell :)

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

El osacompilecompilará el'do shell script "XXX"' fragmento applescript. Su script de shell es el XXX.

Tenga cuidado con las citas, el script de shell debe citarse correctamente para superar el shell que está utilizando para compilarlo aún intacto.

Pero esto se puede ejecutar desde BetterTouchTool sin ninguna locura.


0

Hay otro entrenamiento posible. Proteja su script de shell en un flujo de trabajo de automatización. Invoque el flujo de trabajo con launchd. El codigo es:

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

Esto no iniciará ningún programa ni aparecerá en la barra de menú y es mucho más silencioso que una aplicación Platypus.

Una forma aún mejor de ejecutar scripts de shell es directa en launchd.

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

ejecutará el comando ultra silenciosamente en segundo plano.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.