Maison  >  Article  >  Tutoriel système  >  lxc exec : découvrez son charme unique

lxc exec : découvrez son charme unique

WBOY
WBOYavant
2023-12-30 17:25:53966parcourir
Présentation
Récemment, j'ai apporté plusieurs améliorations à lxc exec. Si vous ne le savez pas, permettez-moi de le présenter. lxc exec est l'outil client de LXD. Il utilise l'API client LXD pour communiquer avec le démon LXD et exécuter divers programmes que l'utilisateur souhaite exécuter. de ce que vous pouvez utiliser :

lxc exec 的魅力特征

L'un de nos principaux objectifs est de rendre lxc exec similaire à ssh, car c'est la norme pour exécuter des commandes à distance, de manière interactive ou non interactive. Cela rend la bonne exécution de lxc un peu délicate.

1. Traiter les tâches en arrière-plan

Un problème de longue date est bien sûr de savoir comment gérer correctement les tâches en arrière-plan. Voici un exemple de problème sur une instance LXD 2.7 :

lxc exec 的魅力特征

Vous pouvez voir que l'exécution de tâches en arrière-plan entraînera l'échec de la fermeture de lxc exec. De nombreuses commandes peuvent déclencher ce problème :

chb@conventiont|~ 
> lxc exec zest1 bash 
root@zest1:~# yes &
 y
 y 
 y 
 . 
 . 
 .

Rien ne peut vous sauver maintenant. oui, j'écrirai toujours directement sur la sortie standard.

La racine du problème est que la sortie standard est toujours ouverte, mais cela est nécessaire car elle est utilisée pour garantir que toutes les données écrites par le processus démarré par l'utilisateur sont effectivement lues et renvoyées via la connexion websocket que nous avons établie.

Si vous souhaitez faire cela, exécutez une session shell, puis exécutez un processus en arrière-plan et quittez immédiatement le shell. Désolé, cela ne fonctionne pas comme prévu.

La première et primitive approche consiste simplement à fermer stdout une fois que vous détectez que le programme de premier plan (par exemple, le shell) s'est terminé. Mais ce n'est pas aussi grave qu'il y paraît. Ce problème devient évident lorsque vous exécutez des programmes à exécution rapide, tels que :

lxc exec -- ls -al /usr/lib

Ici, le processus d'exécution lxc (et le processus forkexec associé. Mais n'y pensez pas maintenant, rappelez-vous simplement que Go + setns() n'interagissent pas...) se terminera avant que toutes les données mises en mémoire tampon dans stdout n'aient été lues . Cette situation entraînera une production tronquée, dont personne ne veut. Après avoir essayé plusieurs méthodes pour résoudre le problème, y compris la désactivation de la mise en mémoire tampon pty (laissez-moi vous dire que ce n'est pas joli et ne fonctionne pas comme prévu.) et d'autres idées étranges, j'ai réussi à passer par quelques "astuces" poll() ( Dans un sens, une « astuce » résout ce problème. Vous pouvez désormais enfin exécuter des tâches en arrière-plan et quitter complètement. Comme le montre l'image :

lxc exec 的魅力特征

2. Signaler les codes de sortie provoqués par des signaux

ssh est un excellent outil. Mais une chose que je n'ai toujours pas aimé, c'est que ssh rapporte toujours -1, qui est le code de sortie 255, lorsqu'une commande exécutée par ssh reçoit un signal. C'est ennuyeux lorsque vous voulez comprendre le signal qui a provoqué la fin du programme. C'est pourquoi j'ai récemment implémenté la convention utilisée par les shells standards pour signaler toute sortie provoquée par un signal, 128 + n, où n est défini comme le sémaphore qui a provoqué la sortie de l'exécuteur. Par exemple, sur le signal SIGKILL, vous verriez 128 + SIGKILL = 137 (calculez les codes de sortie pour d'autres signaux fatals comme exercice pour le lecteur). Vous pouvez donc faire ceci :

chb@conventiont|~ 
> lxc exec zest1 sleep 100

Maintenant, envoyez SIGKILL à l'exécuteur (pas à lxc exec lui-même, car SIGKILL n'est pas transmissible).

kill -KILL $(pidof sleep 100)

Vérifiez enfin le code de sortie de votre programme :

chb@conventiont|~
> echo $?
137

Regardez. Cela ne fonctionne apparemment que si a) le code de sortie ne dépasse pas la barrière informatique de 8 bits, et b) lorsque l'exécuteur n'utilise pas 137 pour indiquer le succès (en quoi... intéressant ?!). Aucun des deux arguments ne me semble très convaincant. La première raison est que les sémaphores fatals ne doivent pas dépasser cette plage. Ce dernier parce que (i) c'est un problème d'utilisateur, (ii) ces codes de sortie sont en fait conservés (je pense que oui.), et (iii) vous aurez le même problème pour exécuter le programme localement ou ailleurs.

Le principal avantage que je vois est la possibilité de signaler un statut de sortie précis à l'exécuteur testamentaire. Notez que nous ne signalons pas toutes les instances de programme tuées par des signaux. Par exemple, lorsque votre programme est capable de gérer SIGTERM et de se terminer proprement, LXD n'a pas de moyen simple de le détecter et de signaler que le programme a été tué par le signal. Vous recevrez simplement le code de sortie 0.

3. Signal avant

Ce n'est peut-être pas très amusant (ou peut-être pas, qui sait), mais je trouve cela très utile. Comme vous pouvez le voir dans le cas SIGKILL, j'ai explicitement déclaré que SIGKILL doit être envoyé à l'exécuteur, et non à la commande lxc exec elle-même. C'est parce que SIGKILL ne peut pas être géré dans le programme. La seule chose qu'un programme peut faire est de mourir, comme maintenant... comme dans cet exemple... tout de suite (vous voyez l'idée...). Mais le programme peut gérer de nombreux autres signaux, SIGTERM, SIGHUP', et bien sûr SIGUSR1 et SIGUSR2. Ainsi, lorsque vous envoyez un signal qui peut être géré par lxc exec` mais pas par l'exécuteur, les versions plus récentes de LXD transmettront le signal à l'exécuteur. C'est très pratique dans les scripts.

Quoi qu'il en soit, j'espère que vous avez trouvé ce petit article/charabia de lxc utile. Profitez de LXD, c'est jouer avec une belle bête folle. Veuillez essayer l'expérience en ligne : https://linuxcontainers.org/lxd/try-it/, et pour les développeurs, regardez ici : https://github.com/lxc/lxd et envoyez-nous des correctifs.

Nous n'exigeons pas qu'un CLA soit signé, nous suivons le style du noyau tant qu'il contient une ligne « Signed-off-by ».


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer