Je cours ruby dans un conteneur docker Alpine (c'est un travailleur sidekiq, si cela est important). À un certain point, mon application reçoit des instructions pour passer à une sous-commande. Je dois être en mesure de diffuser STDOUT plutôt que de l'avoir en mémoire tampon. C'est pourquoi j'utilise PTY au lieu de system() ou une autre réponse similaire. Je l'exécution de la ligne de code suivante:Impossible d'envoyer des signaux à traiter créés par PTY.spawn() dans Ruby
stdout, stdin, pid = PTY.spawn(my_cmd)
Lorsque je me connecte au conteneur docker et exécutez ps auxf, je vois ceci:
root 7 0.0 0.4 187492 72668 ? Sl 01:38 0:00 ruby_program
root 12378 0.0 0.0 1508 252 pts/4 Ss+ 01:38 0:00 \_ sh -c my_cmd
root 12380 0.0 0.0 15936 6544 pts/4 S+ 01:38 0:00 \_ my_cmd
Notez comment le processus d'enfant de rubis est « sh -c my_cmd ", qui elle-même a alors un processus" my_cmd "enfant. "My_cmd" peut prendre beaucoup de temps à s'exécuter. Il est conçu pour que l'envoi d'un signal USR1 au processus l'amène à sauvegarder son état afin qu'il puisse être repris plus tard et s'annuler proprement.
Le problème est que le pid retourné par "PTY.spawn()" est le pid du processus "sh -c my_cmd", pas le processus "my_cmd". Alors, quand j'Execute:
Process.kill('USR1', pid)
il envoie USR1 à sh, pas my_cmd, il ne se comporte pas comme il se doit.
Est-il possible d'obtenir le pid correspondant à la commande que j'ai spécifiée? Je suis ouvert aux idées en dehors du domaine de PTY, mais il doit satisfaire les contraintes suivantes:
1) Je dois être en mesure de diffuser la sortie de STDOUT et STDERR comme ils sont écrits, sans attendre qu'ils être vidé (puisque STDOUT et STDERR se mélangent en un seul flux dans PTY, je redirige STDERR vers un fichier et j'utilise inotify pour obtenir les mises à jour).
2) Je dois pouvoir envoyer USR1 au processus pour pouvoir le mettre en pause.
pgrep n'est pas une commande ruby, d'ailleurs. J'ai dû débourser à nouveau pour l'obtenir. –