2 votos

Applescript, ¿cómo montar el servidor remoto sin error si no está disponible?

Intenté hacer esta pregunta hoy mismo, pero finalmente me di cuenta de que había desordenado completamente lo que intentaba preguntar y también publiqué el código script equivocado. Este es el intento #2.

Tengo dos Macs que se reinician automáticamente cada mañana para que todos sus servicios funcionen de forma óptima. Cada Mac necesita montar un volumen en el otro después de arrancar. Esto es bastante fácil de hacer, excepto en el caso de que una máquina se cuelgue durante el reinicio por cualquier motivo.

Si una de las máquinas no está disponible cuando la otra arranca, obviamente su intento de montar la máquina no disponible fallará. El script está diseñado para ejecutarse cada minuto más o menos en un bucle mientras el volumen remoto no haya sido montado, ya que eventualmente lo hará. Pero cuando el montaje falla, produce un diálogo de error en la máquina que intenta realizar el montaje, que entonces rompe el bucle y el script no se repite.

¿Existe una manera en AppleScript para intentar montar un servidor, pero sin un diálogo de error si ese servidor no está disponible en el momento?

Creía que este era el objetivo principal de los bloques de prueba, pero no ha supuesto ninguna diferencia.

Aquí está el script que actualmente ejecuto en el arranque (es una aplicación de Automator). El flujo de trabajo es un bloque Get Specified Server, seguido de un bloque Run AppleScript. Aquí está el AppleScript:

on run {input, parameters}
    try
        set server to (item 1 of input) -- this gets the server address from the Get Specified Servers block
    end try
    set vol to "Streaming"
    tell application "Finder"
        set isConnected to disk vol exists
    end tell
    repeat while isConnected = false -- as long as the volume is not present, try to mount it

        try
            tell application "Finder"
                mount volume server & "/" & vol -- This produces the error dialog and halts the script, if the server is unavailable
            end tell
        end try
        delay 2

        tell application "Finder"
            set isConnected to disk vol exists
        end tell
        if isConnected = false then
            delay 60 -- if the volume still doesn't exist, wait a minute before trying again
        end if

    end repeat
    return input
end run

Todo funciona perfectamente siempre que el volumen remoto esté listo y accesible. Pero si no es así, aparece el diálogo de error.

Edición: He encontrado este hilo y este hilo bastante complicado en otros lugares que intentan abordar el mismo problema, pero no parece que se haya encontrado una solución sencilla y definitiva.

0 votos

Como mencionaste en otro post que el servidor estaba configurado para Compartir archivos , si no está ejecutando un Servidor web también, entonces curl fallará aunque el servidor esté disponible. En ese caso, puede sustituirlo por ping Por ejemplo ping -t 2 -c 1 192.168.2.102 2>/dev/null | awk '/0 packets received/{print $4}' devuelve 0 si falla. Dicho esto, y mencionando algo de otro post sobre el servidor colgado en el reinicio... Dependiendo de en qué parte del proceso se cuelgue, ping podría tener éxito sin el Compartir archivos recurso que está disponible.

0 votos

Buen punto, y no, no tengo un servidor web, así que tendré que ver qué funciona y con qué fiabilidad.

0 votos

Ver mi respuesta editada... @user3439894 tiene toda la razón en que mi método no debería funcionar, ahora que lo pienso. Lo que no sé es por qué funciona...

2voto

user3439894 Puntos 5883

Utilizando un MacOS Catalina sistema como el servidor de archivos con /Users/Shared/Videos como SMB recurso compartido y habiendo hecho un poco de pruebas, encontré lo siguiente ejemplo AppleScript código para que funcione bien al hacer las pruebas con Script Editor de otro sistema en el red en la que el credenciales ya se han guardado en su Llavero :

set ipAddress to "172.16.15.141"
set sharedResource to "Videos"

if workgroupAvailable(ipAddress) then
    mount volume "smb://" & ipAddress & "/" & sharedResource
end if

on workgroupAvailable(ipAddress)
    set workGroup to do shell script ¬
        "smbutil status " & ipAddress & " | awk '/Workgroup:/{print $2}'"
    if workGroup is equal to "" then
        return false
    else
        return true
    end if
end workgroupAvailable

El responde de lo anterior ejemplo AppleScript código eran:

Cuando el recurso compartido no estaba disponible:

 tell current application
    do shell script "smbutil status 172.16.15.141 | awk '/Workgroup:/{print $2}'"
    --> ""
 end tell

Cuando el recurso compartido estaba disponible:

tell current application
    do shell script "smbutil status 172.16.15.141 | awk '/Workgroup:/{print $2}'"
        --> "WORKGROUP"
end tell
tell application "Script Editor"
    mount volume "smb://172.16.15.141/Videos"
        --> file "Videos:"
end tell
Result:
file "Videos:"

Lo que encontré con el uso de la smbutil status comando en curl que en mi red requería httpd que se ejecuta en el servidor y ping que podría responder incluso si el recurso compartido no estaba disponible, era que smbutil status no ha devuelto el Grupo de trabajo nombre si el recurso compartido no estaba disponible para ser montado y a su vez ningún intento de montar se produce si el Grupo de trabajo no está disponible.

Este ejemplo AppleScript código tampoco hizo aparecer ningún cuadro de diálogo en ningún momento cuando el recurso compartido no estaba disponible.

Tenga en cuenta que aunque las pruebas se hicieron con el reiniciando de la servidor de archivos e intentando conectar en varios momentos durante el reiniciar y el sistema realmente disponible, no he podido probar si el sistema se ha colgado durante el reinicio, ya que nunca se ha colgado durante ningún se reinicia . Como sé que este es un tema no resuelto con el reiniciando de su servidor Si lo desea, puede probarlo.

Evidentemente, se puede adaptar el ejemplo AppleScript código para satisfacer sus necesidades específicas.


Nota: El <em>ejemplo </em><strong>AppleScript </strong><em>código </em>es sólo eso y no contiene ningún <em>tratamiento de errores </em>según corresponda. Corresponde al usuario añadir cualquier <em>tratamiento de errores </em>como sea apropiado, necesario o deseado. Eche un vistazo a la <a href="https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_control_statements.html#//apple_ref/doc/uid/TP40000983-CH6g-129232" rel="nofollow noreferrer"><strong>intente </strong></a><em>declaración </em>y <a href="https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_control_statements.html#//apple_ref/doc/uid/TP40000983-CH6g-129657" rel="nofollow noreferrer"><strong>error </strong></a><em>declaración </em>en el <a href="https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html" rel="nofollow noreferrer"><strong>Guía del lenguaje AppleScript </strong></a>. Véase también, <a href="https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_error_xmpls.html#//apple_ref/doc/uid/TP40000983-CH221-SW1" rel="nofollow noreferrer"><strong>Trabajar con errores </strong></a>. Además, el uso del <a href="https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_cmds.html#//apple_ref/doc/uid/TP40000983-CH216-SW10" rel="nofollow noreferrer"><strong>retraso </strong></a><em>comando </em>puede ser necesario entre eventos cuando sea apropiado, por ejemplo <code>delay 0.5</code> con el <em>valor </em>de la <em>retraso </em>ajustado apropiadamente.

0 votos

Muy interesante. Me pregunto si importará que mis SO sean mucho más antiguos (Sierra en ambas máquinas). Tendré que experimentar con esto y ver a dónde llego. ¡Gracias por la respuesta detallada!

1 votos

@JVC, lamentablemente no tengo una MacOS Sierra sistema disponible por el momento para probar, sin embargo no preveo ningún problema al usar esto con MacOS Sierra bajo las mismas condiciones.

0 votos

@JVC, ¿te funciona este método?

1voto

Douglas Puntos 10417

La forma más sencilla y portable de hacerlo sería a través del shell script. La razón es que evitar completamente los diálogos de error emergentes de la GUI que como has comprobado, rompe tu script. Es mejor manejarlos en el shell .

A continuación se muestra un muy corto script bash/zsh script para conectarse a un recurso compartido del servidor en particular. Puedes personalizarlo manipulando las variables de la parte superior. La clave aquí es almacenar la contraseña del usuario en el llavero para que se conecte sin problemas en todas las conexiones posteriores.

El script es en realidad bastante corto; puedes eliminar todo el printf ya que sólo los incluí para que saliera cada paso en la consola para su referencia. Como todos los comandos de Unix, sale con un 0 para una carrera exitosa y un 1 si hubiera algún problema.

n=1                        # initialize iteration variable
max=3                      # max number of attempts
cflag=1                    # initialize connection flag / 0=true; 1=false
sleeptime=5                # number of seconds to sleep between retries
svr="sername.example"      # server name/IP address
loc="Network Share"        # directory/folder location
user="JVC"                 # username which to authenticate with 

#### Code is Below ###

while [ ${n} -le 3 ] && [ ${cflag} -gt 0 ]    #While not connected and attempts < max
do
if  [ ! $(ping -c 1 ${svr}) ]; then
  printf "Attempt ${n}: Device ${svr} not ready. Sleeping for retry...\n"
  sleep ${sleeptime}
  n=$(( ${n} + 1 ))               # increase count
else 
  cflag=0                         # Set connection flag to "true"
  printf "Device found.  Connecting to "
  printf "smb://${user}@${svr}/${loc}.\n"
  open "smb://${user}@${svr}"     # Connect and mount the share
fi 
done

# Print error message and exit with appropriate exit code.
if [ ${n} -eq ${max} ]; then
  printf "Could not connect to ${svr} in ${n} tries. Giving up."
  exit 1
fi
exit 0

0 votos

Ah, muy bonito. Parece que hay muchas formas potenciales de romper esta nuez, pero todas necesitan más uso de la cáscara. Jugaré con esto y veré lo que consigo. Gracias.

0 votos

Montar un archivo compartido es un proceso Unix, por lo que en realidad funciona "mejor" en el shell que en AS. Yo uso AS para scribir la GUI - para cosas del sistema, prefiero un script de la shell.

0 votos

OMI ping no es un indicador infalible de que un recurso compartido está disponible para ser montado porque ping puede, efectivamente, tener éxito con una respuesta satisfactoria de la dirección IP mientras el recurso compartido aún no está disponible para ser montado. Esto es especialmente cierto para el OP ya que su servidor se cuelga al reiniciar. Puede/podría colgarse fácilmente en un punto en el que ping pero las acciones aún no están disponibles. Esta es la razón por la que después de que ya había sido mencionado por mí en un comentario a la OP y mencionado de nuevo por Wowfunhappy opto por seguir y responder sobre la base de una diferente verbo de smbutil mencionado por klanomath.

0voto

Wowfunhappy Puntos 33

Me encontré con este problema hace algún tiempo, y mi solución fue usar curl de antemano para determinar si una dirección era accesible.

Haz una subrutina para comprobar si existe una dirección:

on addressExists(address)
    try
        do shell script "curl -I --connect-timeout 0.5 'http://" & address & "'" --will error if address does not exist
        return true
    on error
        return false
    end try
end addressExists

Entonces conéctate al servidor sólo si la subrutina dice que es accesible:

if addressExists(serverAddress) then
    tell application "Finder" to mount volume "smb://" & serverAddress
end if

Lo difícil aquí: notarás que el addressExists la subrutina anexa http:// al principio -como necesita curl- mientras que el script principalañade smb:// como necesita Finder. Asegúrese de que la variable de la dirección del servidor no contiene un protocolo.

Si sirve de ayuda, aquí está el proyecto más grande en el que utilicé esto: https://github.com/ideasonpurpose/NAS-Location-Sharing-Workflow

Nota de compatibilidad menor: este método funciona en 10.12 y superiores, pero no funciona en 10.9. Nunca lo he probado en 10.10 o 10.11.


Edición: Un comentario anterior de @user3439894 señaló que esto realmente no debería funcionar. Una máquina que sirve sobre samba no debería servir nada sobre http.

Pero, es hizo me funciona, y sigue funcionando. Toda mi empresa utiliza este script con bastante frecuencia, y el Mac Mini al que nos conectamos no tiene activado el uso compartido de la web. Pero, sólo he probado este método con ese único servidor mac mini, así que no sé si será universal.

Utilizando ping sería probablemente más robusto que curl Aunque estoy bastante seguro de que primero probé con el ping y no conseguí que funcionara de forma fiable. Sin embargo, no recuerdo exactamente, ya que han pasado un par de años.

Es posible que en las próximas dos semanas vuelva a sumergirme en esto para mis propios fines, y actualizaré esta respuesta si lo hago...

0 votos

Aha! Estaba pensando en estas líneas pero no podía averiguar cómo comprobar si un servidor estaba disponible, sin solicitar realmente el montaje. Lo intentaré e informaré... ¡¡Gracias!!

1 votos

¿Por qué no reemplaza rizo con smbutil ? (Ejemplos: smbutil view //user:password@hostname | grep "share_name" o smbutil view //user:password@hostname 2>/dev/null | awk ... que no tiene resultados en caso de error o lista todas las acciones si el smb está disponible)

1 votos

En mi red, la solución que propones, tal como está, sólo funciona si httpd ¡se está ejecutando en la dirección IP de destino! Como mencioné en mi comentario, para el propósito del OP (su servidor a veces se cuelga durante un reinicio mencionado en otro post), "Dependiendo de dónde en el proceso se cuelga, ping podría tener éxito sin el Compartir archivos recurso disponible". Así que ping tampoco es una solución perfecta.

-2voto

qarma Puntos 71

Determinar si una URL es accesible

Esto es algo que es mucho más sencillo de lo que la gente piensa, pero también no suele ser lo primero que se le ocurre a nadie porque este es uno de los pocos usos prácticos de la función de AppleScript URL clase.

Puede tomar una URL de Internet cotidiana como una cadena y coaccionarla para que escriba la clase URL Por ejemplo

"https://duckduckgo.com" as URL

que devuelve el siguiente registro:

{
    class: URL, 
    scheme: secure http URL, 
    path: "https://duckduckgo.com", 
    host: {
        class: Internet address, 
        DNS form: "duckduckgo.com", 
        port: 443, 
        dotted decimal form: "52.213.95.108"
    }
}

(aunque AppleScript no lo imprimirá). Aquí hay una coerción similar usando una dirección web que sé que no existe:

"https://quackquackyo.com" as URL
    --> {
            class: URL, 
            scheme: secure http URL, 
            path: "https://quackquackyo.com", 
            host: {
                class: Internet address, 
                DNS form: "quackquackyo.com", 
                port: 443
            }
        }

Entonces es sólo un juego de detecta la diferencia si una URL se resuelve a una dirección alcanzable, el programa de AppleScript URL devuelve un objeto de clase dotted decimal form que representa la dirección IP del servidor; si la URL no se resuelve, se omite esta dirección IP.

Utilizando este discriminador, podemos crear un manejador que devuelva true o false dependiendo de si una determinada URL es accesible o no:

on urlIsReachable(www as URL)
    local www
    set www to www's host & {dotted decimal form:false}
    return www's dotted decimal form ≠ false
end urlIsReachable

Para usar:

urlIsReachable("https://www.google.com")    --> true
urlIsReachable("https://CK-mac.local")      --> true
urlIsReachable("http://CK.local")           --> true
urlIsReachable("http://CK-maaaaaaac.local") --> false

Tenga en cuenta, sin embargo, que esto no le dice que las máquinas en mi red llamada CK-mac y CK tienen el afp o smb puertos de intercambio de archivos abiertos, y tratando de resolver un afp:// o smb:// arrojará un error, porque el URL El objeto de clase no reconoce muchos esquemas. También significa que si una máquina ha cerrado su http o https (80 y 443, respectivamente), entonces estos devolverán false aunque los puertos 445 ( smb ) o 548 ( afp ) están abiertos. Así que, aunque este método tiene limitaciones, no creo que sea una situación muy común que los puertos de intercambio de archivos estén abiertos en una máquina con los puertos de transferencia de hipertexto específicamente cerrados. El método de AppleScript URL La clase también reconoce ftp:// URLs, pero si se resuelve para cualquiera de sus dispositivos personales, probablemente debería desactivar su ftp servidor para que no lo haga.

Cómo determinar si un disco está montado en Finder

Parece que tienes un método para determinar si un disco está montado o no en tu sistema de archivos, y es uno perfectamente adecuado. Sin embargo, siempre soy consciente de lo temperamental que es Buscador puede ser, y la facilidad con la que se bloquea al hacer otras tareas. Por lo tanto, personalmente, si puedo evitar involucrarlo (en casi todo), lo haré. Y, por supuesto, si puedes aprovechar las capacidades integradas de AppleScript sin llamar a otra aplicación para hacer un trabajo, eso (casi) siempre va a ser más rápido y más fiable. Así que, con este fin, aquí hay un manejador rápido:

on volumeIsMounted(name as text)
    local name
    "/Volumes/" & name as «class furl» as {alias, text}
    return result's class ≠ text
end volumeIsMounted

Para usar:

volumeIsMounted("MEDIA LIBRARY")      --> true
volumeIsMounted("rsaref")             --> true
volumeIsMounted("MEDIAAAAAA LIBRARY") --> false

Como referencia, "MEDIA LIBRARY" es el nombre del disco remoto en mi red conectado a la máquina CK.local que se monta como un afp fileshare con el fin de hacer pruebas. También quería probar un servidor remoto-remota, así que monté un ftp servidor disponible para todos en "ftp://static.zedz.net/pub/security/cryptography/libraries/math/rsaref" (esto no significa que yo respalde la seguridad de abrir cualquier archivo que puedas encontrar en este servidor, así que simplemente sé considerado antes de considerar el acceso a cualquier archivo compartido al azar a través de Internet). "MEDIAAAAAA LIBRARY" Supongo que ya lo sabes, es no montado en mi sistema de archivos.


Esto realmente libera a todo tu script de tener que usar Buscador en absoluto. mount volume es un Adiciones estándar por lo que no es necesario utilizarlo en un Buscador tell y será más eficaz si no lo es. Nada más aquí o en su script requiere Buscador o bien. Eso es una victoria, en mi opinión.

0 votos

Me gusta tu lógica a la hora de plantear un script así, pero me has perdido completamente con la comprobación de las URLs, ya que se trata estrictamente de montar volúmenes remotos en red local, y no veo nada en ningún sitio que haga esto. Tal vez no entiendo AppleScript lo suficientemente bien como para interpretar cómo funciona este script, pero no veo un mount volume comando en cualquier lugar, así que ¿cómo se monta algo?

0 votos

OK, espera, creo que ahora lo entiendo. Esto no se supone que monte nada, esto es sólo para decir si un volumen está disponible o no, entonces si lo está debería ser capaz de montarlo. ¿Si?

0 votos

Bueno, he intentado usar esto pero no consigo averiguar dónde debe ir o cómo debe implementarse. Me gusta el pensamiento detrás de esto más, así que si usted puede dar una explicación completa de qué hacer con esto que sería genial, de lo contrario voy a seguir tratando otras cosas.

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