Domanda
Qualcuno è stato in grado di avviare una webapp tramite una configurazione webappctl
che specifica una configurazione launchd nella sua webapp.plist
launchKeys
key?
Sfondo
In particolare, con Server.app installato, è possibile, in teoria, configurare applicazioni Web personalizzate che verrebbero visualizzate nella GUI Server.app sotto "Impostazioni avanzate" di una configurazione del sito Web.
Se dai un'occhiata a ReadMe.txt
in /Library/Server/Web/Config/apache2
c'è una sezione che afferma:
webapps/
This directory contains the webapp.plist files for all defined webapps.
See the man page for webapp.plist(8) and webappctl(8).
(Server app man pages are present in /Applications/Server.app/Contents/ServerRoot/usr/share/man/.)
Administrators are strongly encouraged to use the webapp mechanism
instead of modifying virtual host config files directly.
In general, you can place Apache configuration directives in an "Include" file,
and create a webapp.plist file that references that Include file.
You can then activate or de-activate that Include file for the default
sites, or for specific custom sites, by using webappctl(8).
Puoi anche leggere le voci man, come suggerito nel ReadMe.txt da questi comandi del terminale:
man -M /Applications/Server.app/Contents/ServerRoot/usr/share/man/ webapp.plist
man -M /Applications/Server.app/Contents/ServerRoot/usr/share/man/ webappctl
C'è anche una configurazione webapp di esempio /Library/Server/Web/Config/apache2/com.example.mywebapp.plist
che contiene alcuni commenti su come questo plist potrebbe essere configurato.
Configurazione
Nel mio caso ho aggiunto un webapp.plist
alla directory /Library/Server/Web/Config/apache2/
che assomiglia a questo:
<?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">
<!-- See man pages for webapp.plist(5) and webappctl(8) for information about webapp.plist -->
<plist version="1.0">
<dict>
<key>includeFiles</key>
<array/> <!-- Include files are activated in virtual host when webapp is started -->
<key>launchKeys</key>
<array> <!-- Launchd plists in /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons are loaded when webapp is started -->
<string>org.levi.foo</string>
</array>
<key>name</key>
<string>org.apache.tomcat</string>
<key>displayName</key> <!-- Name shown in Server app -->
<string>Tomcat</string>
<key>proxies</key> <!-- ProxyPass/ProxyPassReverse directives are activated when webapp is started -->
<dict/>
<key>requiredModuleNames</key>
<array/>
<key>installationIndicatorFilePath</key> <!-- The presence of this file indicates web app is installed -->
<string>/Library/Tomcat/Home/bin/catalina.sh</string>
<key>sslPolicy</key> <!-- Determines webapp SSL behavior -->
<integer>0</integer> <!-- 0: default, UseSSLWhenEnabled -->
<!-- 1: UseSSLAlways -->
<!-- 2: UseSSLOnlyWhenCertificateIsTrustable -->
<!-- 3: UseSSLNever -->
<!-- 4: UseSSLAndNonSSL -->
</dict>
</plist>
Prestare particolare attenzione a:
<key>launchKeys</key>
<array>
<string>org.levi.foo</string>
</array>
che specifica il mio launchd.plist
che si trova in /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons/org.levi.foo.plist
e assomiglia a:
<?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>org.levi.foo</string>
<key>RunAtLoad</key>
<true/>
<key>Program</key>
<string>/Library/Tomcat/start.sh</string>
</dict>
</plist>
che dovrebbe semplicemente chiamare lo script /Library/Tomcat/start.sh
che è semplicemente:
#!/bin/bash
BASENAME='basename $0'
LOGGER_B="/usr/bin/logger"
function log {
MESSAGE="$1"
${LOGGER_B} -i -p daemon.notice -t ${BASENAME} ${MESSAGE}
}
log "Here I am!"
Problema
Se utilizzo launchctl
per caricare manualmente org.levi.foo.plist
:
$ sudo launchctl load org.levi.foo.plist
Ottengo il messaggio previsto in /var/log/system.log
:
Apr 2 16:12:01 host sudo[85791]: levi : TTY=ttys000 ; PWD=/Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons ; USER=root ; COMMAND=/bin/launchctl load org.levi.foo.plist
Apr 2 16:12:01 host start.sh[85795]: Here I am!
Tuttavia, se utilizzo webappctl
per avviare la mia configurazione webapp (sopra):
$ sudo webappctl start org.apache.tomcat
Ottengo un errore in /var/log/system.log
:
Apr 2 16:18:46 host sudo[85904]: levi : TTY=ttys000 ; PWD=/Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons ; USER=root ; COMMAND=/Applications/Server.app/Contents/ServerRoot/usr/sbin/webappctl start org.apache.tomcat
Apr 2 16:18:47 host serverctl[85914]: ERROR: The operation couldn’t be completed. Operation not permitted
Apr 2 16:18:49 host serverctl[85915]: ERROR: The operation couldn’t be completed. Operation not permitted
Apr 2 16:18:49 host servermgr_web[85908]: XSWebConfig:ERROR: Failed on second attempt to load /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons/org.levi.foo.plist
e non vedo il mio "Eccomi!" messaggio.
Questo sembra indicare che il mio launchd.plist
non lo sta facendo per quanto riguarda l'esecuzione dello script quando provo ad avviare tramite webappctl
, ma non ho idea di quale operazione non possa essere completata, o perché no. Tutti i file che ho menzionato sono di proprietà di root:wheel
con autorizzazioni rw-r--r--
, ad eccezione dello script, che è rwx-r-xr-x
.
Quindi, quale magia deve essere eseguita per ottenere la mia webapp per caricare / scaricare la mia configurazione di launchd all'avvio / stop?
Nota a margine: Ovviamente queste configurazioni e script sono semplici esempi che ho usato per scopi di debug e per semplificare qui i dettagli. In realtà sto provando a mettere in piedi un'istanza di Tomcat come "webapp" per eseguire Apache 2 sul mio server in modo tale da poter distribuire app web vere tramite Tomcat e farle pubblicare sul web.)
Nota a margine 2:
So che posso installare il mio launchd.plist
in /Library/LaunchDaemons
e omettere launchKeys
dal mio webapp.plist
come soluzione alternativa, ma ciò non mi consente di avviare / interrompere l'applicazione web tramite Server.app (o la riga di comando equivalente), e, voglio dire, dovrebbe funzionare, giusto?
Grazie mille,
Levi
(crosspost da link )