Le terminal de travail est Windows. Il existe des dizaines de serveurs Unix pour l'exploitation / la maintenance. Le but est de générer les données nécessaires au format CSV sur ce serveur basé sur Unix et de les presser sous Windows. Les langages suivants sont ksh93 et Python
Je me suis connecté à chaque serveur, j'ai lancé une commande et j'ai pris les données sous forme de texte. Il ne peut y avoir une telle inefficacité. Je vais l'améliorer!
Distribuez un script (ci-après moge.sh) qui convertit les données nécessaires en CSV sur chaque serveur Unix. Cela le raccourcit à quelques minutes par unité. Après avoir exécuté le script sur des dizaines d'unités, récupérez-le avec Filezilla, etc. Alors devenez fou sur Windows. Toujours gênant.
Rendons possible de démarrer des scripts sur tous les serveurs sur un serveur, puis copions-les. Comme ça
kicker.ksh
cat servers.list | while read HOST ; do
ssh ${HOST} -n /hoge/moge.sh
scp ${HOST}:/hoge/moge.csv ./data/${HOST}.csv
done
Lorsque vous avez terminé, récupérez tous les CSV d'un avec Filezilla, etc. Mais ** série **, il faut donc ** 1 heure ** pour terminer le script.
Puisque ssh est lent, vous devriez le mettre en arrière-plan. C'est pourquoi ça ressemble à ça
kicker2.ksh
cat servers.list | while read HOST ; do
ssh ${HOST} /hoge/moge.sh &
PID[${HOST}]=$!
done
while [[ ${#PID[*]} -ne 0 ]] ; do
for HOST in ${!PID[*]} ; do
if ! ps -ef | grep -w ${PID[${HOST}]} ; then
scp ${HOST}:/hoge/moge.csv ./data/${HOST}.csv
unset PID[${LPAR}]
fi
done
sleep 1
done
Cela n'a pris que quelques minutes, mais après tout, les éléments de type Filezilla sous Windows étaient gênants.
Le langage a été choisi car Python, qui peut créer Excel, est pratique pour bousiller CSV.
kicker3.py
with open("server.lst", "r", encoding='shift-jis') as fd:
for host in fd:
proc = subprocess.Popen(["ssh", host, "/hoge/moge.sh"], stdout=DEVNULL, stderr=DEVNULL)
proclist[proc.pid] = proc
while proclist:
for pid in list(proclist):
if proclist[pid].poll() is not None:
del proc[pid]
subprocess.Popen(["scp", host + ":/hoge/moge.csv", "./" + host + ".csv"], stdout=DEVNULL, stderr=DEVNULL)
sleep(1)
Cela fonctionne avec WSL, mais ** s'arrête au milieu ** pour les invites de commande. Cela fonctionne si vous réduisez le contenu de server.list (jusqu'à 5 à 6). Pourquoi?
Je n'ai pas du tout compris, donc pour le moment, il vaut mieux l'exécuter de manière asynchrone avec asyncio de Python. Cela peut être bon. Alors j'ai commencé des recherches. Après de nombreux rebondissements, ça ressemble à ça.
kicker4.py
async def _run(host):
ssh = "ssh %s /hoge/moge.sh" % host
p = await asyncio.create_subprocess_exec(ssh, stdout=DEVNULL, stderr=DEVNULL)
await p.wait()
scp = ["scp", host + ":/hoge/moge.csv", "./" + host + "%s.csv"]
p = subprocess.run(scp, stdoutDEVNULL, stderr=DEVNULL)
loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(loop)
with open("server.lst", "r", encoding='shift-jis') as fd:
funcs = asyncio.gather(*[_run(host) for host in fd])
loop.run_until_complete(funcs)
Cela ne fonctionne pas non plus. L'événement ne change pas du tout. Ce que j'ai remarqué ici. ** Déplacez-vous lorsque vous appuyez sur * Entrée * lorsque vous vous arrêtez **. Pourquoi? Y a-t-il un problème avec l'entrée standard?
La bonne réponse est écrite dans le premier script ksh.
Cela est dû à l'option ** "-n" ** de ssh.
Dans ksh, read et ssh sont en conflit avec l'entrée standard, j'ai donc pensé que "-n" était nécessaire, donc
Je le portais depuis le début. Cependant, Python a une entrée standard autre que ssh.
Il semble que le préjugé selon lequel il était normal de ne rien faire était un problème.
Il semble que l'entrée standard nécessite un contrôle lors du lancement de plusieurs ssh en arrière-plan.
(stdin = subprocess.DEVNULL
était inutile)
Le fait que cela ait fonctionné avec WSL reste un mystère, mais je ne vais pas l'étudier car je ne l'utilise plus.
Dans mon script Python, j'utilise également openpyxl pour Gonyo Gonyo sous Windows. Si c'est sur WSL, il mange parfois BSOD, donc cela fonctionne à partir de l'invite de commande Il a été réparé comme suit.
Pourquoi existe-t-il plusieurs façons de donner des commandes au sous-processus? J'aimerais pouvoir l'unifier.