Assez nouveau pour Jenkins et j'ai un problème simple mais ennuyeux. Lorsque j'exécute job (Build) sur Jenkins, je déclenche la commande Ruby pour exécuter mon script de test.
Le problème est que Jenkins n'affiche pas la sortie en temps réel de la console. Voici le journal des déclencheurs.
Building in workspace /var/lib/jenkins/workspace/foo_bar
No emails were triggered.
[foo_bar] $ /bin/sh -xe /tmp/hudson4042436272524123595.sh
+ Ruby /var/lib/jenkins/test-script.rb
Fondamentalement, il se bloque sur cette sortie jusqu'à ce que la génération soit terminée qu'il ne montre simplement la sortie complète. Ce qui est drôle, c'est que ce n'est pas un comportement cohérent, parfois cela fonctionne comme il se doit. Mais la plupart du temps, il n'y a pas de sortie de console en temps réel.
Version Jenkins: 1.461
Pour clarifier certaines des réponses.
Ruby
ou python
ou tout autre langage de script sensible tamponnera la sortie; ceci afin de minimiser les E/S; l'écriture sur le disque est lente, l'écriture sur une console est lente ...flush()
'éditées automatiquement lorsque vous avez suffisamment de données dans le tampon avec une gestion spéciale pour les retours à la ligne. par exemple. écrire une chaîne sans retour à la ligne alors sleep()
n'écrirait rien tant que la sleep()
n'est pas terminée (j'utilise uniquement sleep
comme exemple, n'hésitez pas à remplacer par tout autre appel système coûteux).par exemple. cela attendre 8 secondes, imprimer une ligne, attendre 5 secondes de plus, imprimer une deuxième ligne.
from time import sleep
def test():
print "ok",
time.sleep(3)
print "now",
time.sleep(5)
print "done"
time.sleep(5)
print "again"
test()
pour Ruby
, STDOUT.sync = true
, active le autoflush
; toutes les écritures dans STDOUT
sont suivies de flush()
. Cela résoudrait votre problème mais entraînerait davantage d'E/S.
STDOUT.sync = true
pour python
, vous pouvez utiliser python -u
ou la variable d'environnement PYTHONUNBUFFERED
pour que stdin/stdout/stout
ne soit pas mis en mémoire tampon, mais il existe d'autres solutions qui ne changent pas stdin
ou stderr
export PYTHONUNBUFFERED=1
pour Perl
, vous avez autoflush
autoflush STDOUT 1;
Assurez-vous que votre script le vide stdout, stderr. Dans mon cas, j'ai eu un problème de polissage similaire à ce que vous décrivez, mais j'utilisais python. Le code python suivant l'a corrigé pour moi:
import sys
sys.stdout.flush()
Je ne suis pas un code Ruby mais Google révèle ce qui suit:
$stdout.flush
Il me semble que python -u
fonctionne aussi.
Par exemple. Commande en lot
python -u foo.py
La solution la plus simple consiste à activer la synchronisation du tampon sur la sortie. Quelque chose sur lequel @Craig a écrit dans sa réponse, mais une solution en ligne qui couvrira tout le script et ne vous obligera pas à vider le tampon plusieurs fois.
Ecrivez
STDOUT.sync = true
La logique derrière est simple, pour éviter d'utiliser IO opérations plusieurs fois la sortie est mise en mémoire tampon. Pour désactiver cette utilisation
STDOUT.sync = false
C'est Ruby solution ofc.
Chacune des autres réponses est spécifique à un programme ou à un autre, mais j'ai trouvé une solution plus générale ici:
https://unix.stackexchange.com/a/25378
Vous pouvez utiliser stdbuf
pour modifier le comportement de mise en mémoire tampon de n'importe quel programme.
Dans mon cas, je canalisais la sortie d'un script Shell via tee
et grep
pour diviser les lignes en console ou en fichier basé sur le contenu. La console était suspendue comme décrit par OP. Cela l'a résolu:
./slowly_parse.py login.csv |tee >(grep -v LOG: > out.csv) | stdbuf -oL -eL grep LOG:
Finalement, j'ai découvert que je pouvais simplement passer --line-buffered
à grep pour le même résultat:
./slowly_parse.py login.csv |tee >(grep -v LOG: > out.csv) | grep --line-buffered LOG:
Les autres réponses sont correctes en disant que vous devez vous assurer que la sortie standard n'est pas mise en mémoire tampon.
L'autre chose à savoir est que Jenkins lui-même effectue la mise en mémoire tampon ligne par ligne. Si vous avez un processus lent qui émet des caractères uniques (par exemple, un résumé de la suite de tests d'unité qui imprime un .
pour un test réussi et un E
pour une erreur) vous ne verrez rien avant la fin de la ligne.
[Vrai pour mon Jenkins 1.572 fonctionnant sur une boîte Windows.]
Python a mis en mémoire tampon ses traces de sortie et l'affiche à la fin du script pour minimiser l'écriture sur la console car l'écriture sur la console est lente.
Vous pouvez utiliser la commande suivante après vos traces. Il videra toutes les traces sur la console, qui sont mises en file d'attente avant cette commande.
sys.stdout.flush ()
Le système d'exploitation met en mémoire tampon les données de sortie par nature, pour économiser le processeur, tout comme Jenkins.
Il semble que vous utilisiez une commande Shell pour exécuter votre script Ruby -
Je suggère d'exécuter votre script Ruby directement via le plugin dédié:
(peut-être besoin de l'installer)