2017-08-01 7 views
0

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.

Répondre

0

J'ai abandonné une solution propre. J'ai finalement juste exécuté

pgrep -P #{pid} 

pour obtenir l'enfant pid, et puis je pourrais envoyer USR1 à ce processus. Se sent hacky, mais quand ruby ​​vous donne des citrons ...

+0

pgrep n'est pas une commande ruby, d'ailleurs. J'ai dû débourser à nouveau pour l'obtenir. –