4 votos

MacOS Catalina: ejecutar bash script en el arranque con launchctl

Antes de actualizar a Catalina (10.15.1) mi agente basado en un bash script funcionaba perfectamente.

Había configurado el agente para que ejecutara el bash script en el arranque. Aquí está el archivo plist:

<?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>Label</key>
        <string>mark.battery.info</string>
        <key>Program</key>
        <string>/Users/mark/Dropbox/Exec/BatteryInfoOnBoot.sh</string>
        <key>RunAtLoad</key>
        <true/>
    </dict>
</plist>

Después de la última actualización me di cuenta de que el script (BatteryInfoOnBoot.sh) ya no se cargaba en el arranque y si ejecuto el comando:

launchctl list | grep mark
-   1   mark.battery.info

He leído que el estado 1 significa:

PID - El estado 1 significa que el proceso no tiene suficientes privilegios para acceder a algunos archivos

ref

El script BatteryInfoOnBoot es muy sencillo:

#!/bin/bash

echo "~~~~~~~~~"  >> /Users/mark/Documents/battery-log.txt
date  >> /Users/mark/Documents/battery-log.txt
/Users/mark/Dropbox/Exec/BatteryInfo.sh >> /Users/mark/Documents/battery-log.txt

en cambio BatteryInfo.sh se utiliza sólo para obtener alguna información útil:

#!/bin/bash

echo "Current battery percentage:"
pmset -g batt | grep -Eo "\d+%" | cut -d% -f1
echo ""

echo "Cycle count:"
system_profiler SPPowerDataType | grep "Cycle Count"
echo ""

echo "Capacity stats:"
ioreg -brc AppleSmartBattery | grep -i capacity | grep -v Legacy | grep -v BatteryData | grep -v AppleRaw
echo ""

PD: el script sigue funcionando si lo ejecuto manualmente:

/Users/mark/Dropbox/Exec/BatteryInfoOnBoot.sh

¿Alguna sugerencia?

6voto

klanomath Puntos 19587

/Usuarios/marca/Documentos/ es una carpeta de usuario protegida (como Descargas y Escritorio).

Normalmente se pueden añadir aplicaciones a System Preferences > Security & Privacy > Privacy > Full Disk Access para permitir el acceso a estas carpetas. El terminal ya está añadido probablemente - la razón por la que no se muestra ningún error ejecutando el script manualmente.

Cambiar el destino del archivo de registro en el shell script BatteryInfoOnBoot.sh a /Users/mark/Library/Logs/ y funcionará.

Prueba (Máquina virtual - sin batería dentro ;-)):

user@host ~ % cat Library/Logs/battery-log.txt 
~~~~~~~~~
Tue Dec  3 01:23:55 CET 2019
Current battery percentage:

Cycle count:

Capacity stats:

Como alternativa no deseada (porque incluso los archivos de registro a-típicos pertenecen a ~/Library/Logs/ o /Library/Logs/ ) puedes mantener tu archivo original tal cual, pero tienes que añadir /bin/launchctl a System Preferences > Security & Privacy > Privacy > Full Disk Access entonces.

Prueba (todavía sin batería dentro):

user@host ~ % cat Documents/battery-log.txt 
~~~~~~~~~
Tue Dec  3 01:32:30 CET 2019
Current battery percentage:

Cycle count:

Capacity stats:

0 votos

¡gracias gracias gracias todo funciona bien ahora! Recapitulemos: Preferencias del Sistema > Privacidad y Seguridad > Seguridad > Acceso total al disco para habilitar la aplicación Terminal + archivo plist en ~/Librería/LaunchAgents + archivo de salida en ~/Librería/Logs, mientras que bash scripts puede permanecer en la (sub)carpeta Documentos :-)

0 votos

@suikoy Lo he probado con el plist en /Library/LaunchAgents.

1voto

vatw Puntos 1

Para mí, lo que funcionó

No he tenido mucha suerte con el proceso recomendado aquí por otros (dar acceso completo) - quería llamar a un rsync periódicamente para hacer una copia de seguridad de una carpeta de trabajo crítica a otro servidor (no Mac).

Incluso cuando le di a cron y launchctl y launchd y rsync (lo intenté todo) al 'acceso completo', recibía errores indicando que el proceso (rsync) no tenía acceso a la ruta de archivo apropiada. (probablemente hay algún otro proceso que se me escapa) -- Tampoco me gusta la idea de dar a cosas como 'cron' acceso completo en caso de que algo malicioso se instale en mi crontab.

Lo que finalmente funcionó para mí fue un poco loco, pero escribí una rápida aplicación de Mac (O realmente, una "herramienta de línea de comandos" swift como Xcode lo llama), que acaba de ejecutar el comando shell necesario que quería de todos modos- - y modificado mi agente de usuario para llamar a la aplicación swift compilado - a continuación, el sistema operativo me pedirá que conceder acceso a ~ / documentos para la aplicación swift, que luego puso en marcha el shell script (Que luego llamó a rsync) - whew.

Mi swift App tiene unas 5 líneas:

//localrsync
//main.swift

import Foundation

let task = Process()
task.launchPath = "~/bin/backDocsRsync.sh"
task.launch()
task.waitUntilExit()
print(task.terminationStatus)

y luego simplemente puse el producto compilado de Xcode en mi carpeta ~/bin, y apunté mi UserAgent a eso:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>local.backdocs.rsync</string>
    <key>ProgramArguments</key>    
    <array>
        <string>~/bin/localrsync</string>
    </array>
    <key>StartInterval</key> 
    <integer>7200</integer>
    <key>StandardErrorPath</key>
    <string>~/Library/Logs/rsync.log</string>
    <key>StandardOutPath</key>
    <string>~/Library/Logs/rsync.log</string>
</dict>
</plist>

(y sí, sé que hay formas "mejores" que rsync, pero esto funciona bien para la combinación de diferentes hardware y sistemas operativos que tengo disponibles)

Para hacer todo esto, necesitas tener Xcode instalado, o al menos disponible, lo que requiere al menos una cuenta gratuita de desarrollador de Apple, y tal vez algunas otras cosas. No estoy seguro de si puedes compilar aplicaciones Mac autofirmadas sin pagar por un perfil de aprovisionamiento para desarrolladores o no, así que si realmente quieres hacer esto, no estoy seguro de qué recomendar.

0 votos

Gracias. Esto me ha funcionado muy bien. Terminé escribiendo una simple aplicación C en lugar de Swift que sólo fork/exec'd el bash script, pero el mismo concepto. Yo también le concedió acceso completo al disco en lugar de esperar a que las ventanas emergentes. Pero el mismo concepto, y significa que puedo limitar la concesión de permisos a sólo esta aplicación.

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X