2
votes

Utilisation de boucles for bash en conjonction avec applescript intégré pour les scripts bash

J'essaie de faire en sorte qu'applescript interagisse avec la boucle bash for qui fait partie de mon code pour éviter d'avoir à lister chaque hôte manuellement et d'exécuter des blocs tell / end tell individuels pour chaque hôte trouvé dans hosts2.txt

Le but du script est d'ouvrir un nouvel onglet de terminal sur mon Mac et de lancer automatiquement "screen -r $ HOST" dans chaque nouveau terminal jusqu'à la fin de la liste d'hôtes dans le document hosts2.txt. Chaque hôte est répertorié sur sa propre ligne.

J'ai essayé une boucle for tout compris, sans le code applescript "repeat 2 times" "end repeat" qui est montré ci-dessous. Il se répète 2 fois car il n'y a que 2 hôtes répertoriés dans le document texte à des fins de test. Chaque fois que j'ai une sortie d'erreur.

dev
44:52: syntax error: Expected end of line but found command name. (-2741)
pulsar
44:52: syntax error: Expected end of line but found command name. (-2741)

Ce que j'attends, c'est que le code exécute l'ouverture de nouveaux onglets de terminal avec screen -r pour chaque hôte. La sortie d'erreur est en dessous de cette ligne.

#!/bin/bash

for HOST in `cat ~/bin/hosts2.txt`
do echo $HOST
    osascript -e 'repeat 2 times
    tell application "Terminal" activate
tell application "System Events" to keystroke "t" using [command down]
tell application "Terminal" to activate
set host to $HOST
tell application "Terminal"
do shell script "screen -r " & host in front window
end tell
end repeat'
done


3 commentaires

Question très bien composée avec de bonnes informations, bravo et merci. Question: quelle version de macOS utilisez-vous? De plus, si cela ne vous dérange pas, veuillez publier le contenu de votre fichier ~ / bin / hosts2.txt .


hosts2.txt contient uniquement les éléments suivants: dev pulsar Chacun sur sa propre ligne.


J'ai oublié de répondre à l'autre question. J'utilise Mojave.


3 Réponses :


1
votes

Vous avez une faute de frappe dans votre code.

La ligne dire à l'application "Terminal" activer devrait être dire à l'application "Terminal" d'activer .

Le développement des variables ne fonctionne pas non plus entre guillemets simples dans bash (les guillemets simples signifient que tout est interprété littéralement), donc la ligne set host to $ HOST entre les guillemets simples ne fonctionnera pas.

/ p>

Essayez ceci:

#!/bin/bash

for HOST in `cat ~/bin/hosts2.txt`
do echo $HOST
  osascript -e "repeat 2 times
  tell application \"Terminal\" to activate
  tell application \"System Events\" to keystroke \"t\" using [command down]
  tell application \"Terminal\" to activate
  set host to \"$HOST\"
  tell application \"Terminal\"
  do shell script \"screen -r \" & host in front window
  end tell
  end repeat"
done

Edit: Je pense qu'il y a en fait un autre problème: lors de la définition d'une variable sur une chaîne dans applescript, la chaîne doit être incluse dans citations. Donc, set host sur $ HOST provoque une erreur car il interprète la valeur de $ HOST ("pulsar" ou "dev") comme une commande qu'il est impossible de trouver / exécuter ; il doit être défini l'hôte sur \ "$ HOST \" à la place. Je l'ai changé ci-dessus.


1 commentaires

Ne générez PAS de code exécutable via une interpolation de chaîne brute. C'est extrêmement dangereux , par exemple voir toutes les attaques par injection SQL. Voici la bonne façon de passer des arguments dans un AppleScript. Apprenez-le, transmettez-le.



0
votes

Vous trouverez peut-être un here-doc lisible et facile à utiliser. Utilisez également une boucle while-read pour parcourir les lignes d'un fichier (réf: http: // mywiki .wooledge.org / BashFAQ / 001 )

while read -r host; do
    echo "$host"

    osabody=$(cat << END_OSA
      repeat 2 times
        tell application "Terminal" to activate
        tell application "System Events" to keystroke "t" using [command down]
        tell application "Terminal" to activate
        set host to "$host"
        tell application "Terminal"
          do shell script "screen -r " & host in front window
        end tell
      end repeat
END_OSA
)
    osascript -e "$osabody"
done < ~/bin/hosts2.txt

La parenthèse de fin de la substitution de commande $ (cat ... doit être sur un ligne car le mot de fin de l'hérédoc doit être les seuls caractères de cette ligne.


0 commentaires

1
votes

Il y a quelques problèmes avec votre script: certains l'empêchent de fonctionner complètement; certains qui lui font faire la mauvaise chose; et certains qui n'avaient pas besoin d'être là en premier lieu. Il y a quelques autres réponses qui abordent certains points, mais aucune d'elles n'a semblé tester le script car il y en a beaucoup qu'elles ne traitent pas.

... pour chaque hôte trouvé dans le fichier hosts2.txt ...
... Chaque hôte est répertorié sur sa propre ligne.

Alors cette ligne:

osascript <<OSA
    property home : system attribute "HOME"
    property file : POSIX file (home & "/bin/hosts2.txt")

    set hosts to read my file using delimiter {return, linefeed}

    repeat with host in hosts
        tell application "Terminal" to do script ("screen -r " & host)
    end repeat
OSA

n'est pas ce que vous voulez. Cela créera un tableau à partir de mots individuels, pas de lignes dans le fichier. Vous souhaitez utiliser la commande read , qui lit un fichier ligne par ligne. Vous pouvez structurer une boucle de cette manière:

while read -r HOST; do
    echo "$HOST"
    osascript -e "tell application \"Terminal\" to do script \"screen -r $HOST\""
done < ~/bin/hosts2.txt

Comme @entraz a > a déjà souligné, votre utilisation des guillemets simples empêchera les variables shell de se développer dans votre osascript.

Ensuite, il y a l'AppleScript lui-même.

Je ne sais pas pourquoi vous avez inclus une boucle repeat .

Le but du script est d'ouvrir un nouvel onglet de terminal sur mon Mac et de lancer automatiquement "screen -r $ HOST" dans chaque nouveau terminal jusqu'à la fin de la liste d'hôtes dans le document hosts2.txt. Chaque hôte est répertorié sur sa propre ligne. Il se répète 2 fois car il n'y a que 2 hôtes répertoriés dans le document texte

Cela n'a aucun sens, étant donné que vous avez implémenté une boucle bash afin de lire les lignes dans la variable $ HOST . Certes, vous lisiez des mots, pas des lignes, mais la répétition AppleScript est un grattoir. Débarrassez-le.

Ensuite, vous avez ceci:

tell application "Terminal" to do script "screen -r $HOST"

C'est environ une infinité de fois le nombre que vous devez dire Terminal à activer .

Cette ligne:

tell application "Terminal"
    do shell script "screen -r " & host in front window
end tell

générera une erreur pour deux raisons: premièrement, host est considéré comme un nom existant de une propriété dans les ajouts standard d'AppleScript, vous ne pouvez donc pas la définir sur une nouvelle valeur; deuxièmement, il n'y a pas de guillemets autour de $ HOST , donc il ne sera pas reconnu comme une chaîne. Mais, c'est juste pour votre apprentissage, car nous allons en fait nous débarrasser complètement de cette ligne.

Enfin:

set host to $HOST

est faux. do shell script n'est pas une commande Terminal . C'est une commande appartenant aux ajouts standard d'AppleScript. Par conséquent, si le reste de votre code fonctionnait et qu'il arrivait à cette commande, Terminal n'exécuterait rien. Au lieu de cela, les scripts shell fonctionneraient en arrière-plan sans shell réel, donc ce n'est pas très bon pour vous.

La commande que vous recherchez est do script . P >

Malheureusement, il semble que, dans High Sierra au moins, les commandes AppleScript pour créer de nouveaux onglets et fenêtres dans Terminal ne fonctionnent plus, donc je peux voir pourquoi vous avez eu recours aux Événements système pour créer un onglet comme vous l'avez fait. Heureusement, ce n'est pas nécessaire, et vos multiples commandes activate ne le sont pas non plus: do script exécutera automatiquement Terminal et exécutera un script dans un nouvel onglet en par défaut.

Par conséquent, la seule commande AppleScript dont vous avez besoin est la suivante:

tell application "Terminal" activate
tell application "System Events" to keystroke "t" using [command down]
tell application "Terminal" to activate

Le script final

En mettant tout cela ensemble, voici le script hybride final:

while read -r HOST; do
    .
    .
    .
done < ~/bin/hosts2.txt

Alternativement

Si vous vouliez prendre la boucle de bash et la mettre dans AppleScript à la place, vous pouvez le faire comme celui-ci, pour lequel j'utiliserai un heredoc ( ) pour simplifier l'utilisation des guillemets et faciliter la lisibilité:

for HOST in `cat ~/bin/hosts2.txt`


2 commentaires

Très proche de ce que je souhaite que le script fasse dans votre révision "Final Script". La seule différence est que je veux qu'il ouvre de nouveaux onglets de terminal plutôt que de nouvelles fenêtres, ce que fait votre révision. Le raccourci Commande + T est utilisé dans mon code précédent pour ouvrir un nouvel onglet à chaque fois avant d'exécuter "screen -r $ HOST" Des suggestions?


Dans mon Terminal , il ouvre un nouvel onglet, ce qui signifie qu'il s'agit d'un paramètre que vous définissez dans l'application elle-même. Je vais donc jeter un œil dans les préférences et le configurer pour ouvrir de nouveaux onglets en faveur des fenêtres.