2 votes

Applescript, comment monter un serveur distant sans erreur s'il n'est pas disponible ?

J'ai tenté de répondre à cette question plus tôt dans la journée, mais j'ai finalement réalisé que j'avais complètement déformé ce que j'essayais de demander et que j'avais également posté le mauvais code script. Voici donc la deuxième tentative.

J'ai deux Macs qui redémarrent automatiquement tôt chaque matin afin que leurs différents services fonctionnent de manière optimale. Chaque Mac doit monter un volume sur l'autre après le démarrage. C'est assez facile à faire, sauf dans le cas où une machine se bloque pendant le redémarrage pour une raison quelconque.

Si l'une des machines est indisponible lorsque l'autre démarre, alors évidemment sa tentative de monter la machine indisponible échouera. Le script est conçu pour s'exécuter toutes les minutes environ en boucle tant que le volume distant n'a pas été monté, puisqu'il finira par se monter. Mais lorsque le montage échoue, il produit un dialogue d'erreur sur la machine qui tente d'effectuer le montage, ce qui interrompt alors la boucle et le script ne se répète pas.

Existe-t-il un moyen dans AppleScript de tenter de monter un serveur, mais sans boîte de dialogue d'erreur si ce serveur est indisponible pour le moment ?

Je pensais que c'était l'objectif principal des blocs d'essai, mais cela n'a fait aucune différence.

Voici le script que j'exécute actuellement au démarrage (c'est une application Automator). Le flux de travail est un bloc Get Specified Server, suivi d'un bloc Run AppleScript. Voici l'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

Tout fonctionne parfaitement tant que le volume à distance est prêt et accessible. Mais dans le cas contraire, la boîte de dialogue d'erreur apparaît.

Edit : J'ai trouvé ce fil y ce fil de discussion assez compliqué ailleurs qui tentent de résoudre le même problème, mais aucune solution simple et définitive ne semble avoir été trouvée.

2voto

user3439894 Points 52496

Utilisation d'un MacOS Catalina système comme le serveur de fichiers avec /Users/Shared/Videos comme un SMB ressource partagée et après avoir effectué quelques tests, j'ai trouvé ce qui suit exemple AppleScript code pour bien fonctionner lors des tests utilisant scriptÉditeur d'un autre système sur le réseau dans laquelle le Références ont déjà été enregistrées dans son Porte-clés :

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 répond à de ce qui précède exemple AppleScript code étaient :

Lorsque le ressource partagée n'était pas disponible :

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

Lorsque le ressource partagée était 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:"

Ce que j'ai trouvé en utilisant le smbutil status commande sur curl ce qui, sur mon réseau, nécessite httpd en cours d'exécution sur le servidor et ping qui pourrait répondre même si le ressource partagée n'était pas disponible, c'est que smbutil status n'a pas réussi à renvoyer le Groupe de travail nom si le ressource partagée n'était pas disponible pour être monté et, à son tour, aucune tentative pour mont se produit si le Groupe de travail n'est pas disponible.

Este exemple AppleScript code n'a pas non plus provoqué l'apparition de boîtes de dialogue à un moment quelconque de l'opération. ressource partagée n'était pas disponible.

Notez que, bien que les tests aient été effectués avec le Redémarrage de de la serveur de fichiers et de tenter de connecter à différents moments de l'année redémarrer y el système étant effectivement disponible, je n'ai pas été en mesure de tester si la système s'était bloqué pendant le redémarrage, car il ne s'est jamais bloqué lors d'une quelconque redémarre . Comme je le sais, il s'agit d'un problème non résolu avec la Commission européenne. Redémarrage de de votre servidor Vous pouvez essayer de le faire si vous le souhaitez.

Vous pouvez évidemment adapter le exemple AppleScript code pour répondre à vos besoins spécifiques.


Note : Le <em>exemple </em><strong>AppleScript </strong><em>code </em>est juste cela et ne contient pas de <em>traitement des erreurs </em>comme il se doit. C'est à l'utilisateur qu'il incombe d'ajouter toute <em>gestion des erreurs </em>selon ce qui est approprié, nécessaire ou souhaité. Consultez le <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>essayez </strong></a><em>déclaration </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>erreur </strong></a><em>déclaration </em>dans le <a href="https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html" rel="nofollow noreferrer"><strong>Guide du langage AppleScript </strong></a>. Voir aussi, <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>Travailler avec des erreurs </strong></a>. En outre, l'utilisation de la <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>retarder </strong></a><em>commande </em>peut être nécessaire entre les événements, le cas échéant, par ex. <code>delay 0.5</code> avec le <em>valeur </em>de la <em>retarder </em>définis de manière appropriée.

1voto

Douglas Points 10417

La manière la plus simple et la plus portable de le faire serait via le shell script. La raison en est que vous évitez complètement les boîtes de dialogue d'erreur de l'interface graphique. ce qui, comme vous l'avez constaté, casse votre script. Il est préférable de les gérer dans le shell .

Voici un très court script bash/zsh script pour se connecter à un partage de serveur particulier. Vous pouvez le personnaliser en manipulant les variables dans la partie supérieure. La clé ici est de stocker le mot de passe de l'utilisateur dans le trousseau de clés afin de se connecter de manière transparente lors de toutes les connexions ultérieures.

Le script est en fait assez court ; vous pouvez supprimer tous les éléments du printf car je les ai inclus uniquement pour que chaque étape soit affichée dans la console pour votre référence. Comme toutes les autres commandes Unix, la commande se termine par un message 0 pour une course réussie et un 1 s'il y avait un problème.

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

1voto

mivk Points 807

Pour vérifier si un partage de serveur est disponible et le monter s'il l'est, un shell script serait beaucoup plus simple qu'Applescript.

Et pour vérifier le serveur, il est préférable d'utiliser smbutil plutôt que ping .

Cet exemple Bash script

  • définit le nom du serveur et du partage
  • vérifie si le partage est déjà monté, et se termine si c'est le cas.
  • puis vérifie si le serveur est disponible et si oui, le monte.

    !/bin/bash

    server=my_server share=my_share

    mount | grep -q "^//.*/$share on /Volumes/" && exit 0

    if smbutil status $server 2>/dev/null | grep -q '^Server:'; then open smb://$server/$share else exit 1 fi

Si vous devez fournir des informations d'identification pour monter le partage, vous pouvez les ajouter à la variable du serveur comme ceci :

server="Username:Password@my_server"

0voto

Wowfunhappy Points 6021

J'ai rencontré ce problème il y a quelque temps, et ma solution était d'utiliser curl au préalable pour déterminer si une adresse était accessible.

Créer une sous-routine pour vérifier si une adresse existe :

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

Ensuite, connectez-vous au serveur uniquement si la sous-routine indique qu'il est accessible :

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

Un point délicat ici : vous remarquerez que l'option addressExists La sous-routine ajoute http:// au début - comme c'est nécessaire pour curl - alors que le script principal ajoute smb:// comme l'exige le Finder. Assurez-vous que la variable adresse du serveur ne contient pas elle-même un protocole.

Si cela peut vous aider, voici le projet plus vaste dans lequel j'ai utilisé cette méthode : https://github.com/ideasonpurpose/NAS-Location-Sharing-Workflow

Note de compatibilité mineure : cette méthode fonctionne sur 10.12 et plus, mais pas sur 10.9. Je ne l'ai jamais testée sur 10.10 ou 10.11.


Edit : Un commentaire de @user3439894 a fait remarquer que cela ne devrait pas fonctionner. Une machine servant via samba ne devrait pas servir quoi que ce soit via http.

Mais, il a fait a fonctionné pour moi, et continue de le faire. Toute mon entreprise utilise ce script assez largement, et le Mac Mini auquel nous nous connectons n'a pas le partage web activé. Mais, je n'ai jamais testé cette méthode qu'avec ce seul serveur mac mini, donc je ne sais pas si elle sera universelle.

Utilisation de ping serait probablement plus robuste que curl Bien que je sois presque sûr d'avoir essayé le ping en premier et de ne pas avoir réussi à le faire fonctionner de manière fiable. Je ne me souviens pas exactement, cependant, puisque cela fait quelques années.

Il se peut que je me replonge dans cette question pour mes propres besoins dans les deux prochaines semaines, et je mettrai à jour cette réponse si je le fais...

-2voto

OnePablo Points 1

Déterminer si une URL est accessible

C'est quelque chose de beaucoup plus simple qu'on ne le pense, mais ce n'est pas non plus la première chose qui vient à l'esprit des gens, car c'est l'une des rares utilisations pratiques de l'outil AppleScript URL classe.

Vous pouvez prendre une URL Internet courante sous la forme d'une chaîne et la contraindre à taper la classe URL par exemple

"https://duckduckgo.com" as URL

qui renvoie l'enregistrement suivant :

{
    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"
    }
}

(bien qu'AppleScript ne l'imprimera pas joliment). Voici une coercition similaire utilisant une adresse web dont je sais qu'elle n'existe pas :

"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
            }
        }

Alors c'est juste un jeu de repérez la différence : si une URL se résout en une adresse accessible, l'outil AppleScript URL renvoie un objet de classe dotted decimal form représentant l'adresse IP du serveur ; si l'URL ne se résout pas, cette adresse IP est omise.

En utilisant ce discriminant, nous pouvons créer un gestionnaire qui retourne true o false selon qu'une URL donnée est accessible ou non :

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

A utiliser :

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

Gardez à l'esprit, cependant, que cela ne vous dit pas que les machines sur mon réseau appelé CK-mac y CK ont le afp o smb ports de partage de fichiers ouverts, et en essayant de résoudre une afp:// o smb:// entraînera une erreur, car l'URL URL La classe objet ne reconnaît pas beaucoup de schémas. Cela signifie également que si une machine a fermé son objet de classe http o https (80 et 443, respectivement), ils renverront l'information suivante false même si les ports 445 ( smb ) ou 548 ( afp ) sont ouverts. Ainsi, bien que cette méthode ait des limites, je ne pense pas qu'il soit très courant que des ports de partage de fichiers soient ouverts sur une machine dont les ports de transfert hypertexte sont spécifiquement fermés. La méthode AppleScript URL La classe reconnaît également ftp:// mais s'il se résout pour l'un de vos appareils personnels, vous devriez probablement désactiver sa fonction ftp pour qu'il ne le fasse pas.

Déterminer si un disque est monté dans le Finder

Il semble que vous disposiez d'une méthode pour déterminer si un disque est actuellement monté ou non sur votre système de fichiers, et c'est une méthode parfaitement adaptée. Je suis toujours conscient, cependant, du caractère capricieux de cette méthode. Finder peut être, et la facilité avec laquelle il se bloque lors de la réalisation d'autres tâches. Par conséquent, personnellement, si je peux éviter de l'impliquer (dans à peu près tout), je le ferai. Et, bien sûr, si vous pouvez exploiter les capacités intégrées d'AppleScript sans faire appel à une autre application pour effectuer une tâche, cela sera (presque) toujours plus rapide et plus fiable. Donc, à cette fin, voici un gestionnaire rapide :

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

A utiliser :

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

Pour référence, "MEDIA LIBRARY" est le nom du disque distant sur mon réseau attaché à la machine CK.local qui est monté comme un afp fileshare pour les besoins du test. Je souhaitais également tester un serveur distant, j'ai donc monté un serveur ftp disponible pour tous à l'adresse "ftp://static.zedz.net/pub/security/cryptography/libraries/math/rsaref" (je ne cautionne pas la sécurité de l'ouverture des fichiers que vous pourriez trouver sur ce serveur, soyez donc prudent avant d'envisager d'accéder à un partage de fichiers aléatoire sur Internet). "MEDIAAAAAA LIBRARY" que vous connaissez, je suppose, est no monté sur mon système de fichiers.


Cela libère en fait l'ensemble de votre script de devoir utiliser Finder du tout. mount volume est un Ajouts standard il n'est donc pas nécessaire de l'utiliser dans une commande Finder tell et sera plus performant s'il ne l'est pas. Rien d'autre ici ou dans votre script ne requiert Finder soit. C'est une victoire, dans mon livre.

LesApples.com

LesApples est une communauté de Apple où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres utilisateurs d'appareils Apple, poser vos propres questions ou résoudre celles des autres.

Powered by:

X