J'ai un petit script, qui est appelé quotidiennement par crontab en utilisant la commande suivante:
/homedir/MyScript &> some_log.log
Le problème avec cette méthode est que some_log.log n'est créé qu'une fois MyScript terminé. Je voudrais vider la sortie du programme dans le fichier pendant son exécution afin que je puisse faire des choses comme
tail -f some_log.log
et suivre les progrès, etc.
sys.stdout.flush()
.Réponses:
bash lui-même n'écrira jamais aucune sortie dans votre fichier journal. Au lieu de cela, les commandes qu'il invoque dans le cadre du script écriront chacune individuellement la sortie et videront chaque fois qu'elles le souhaitent. Votre question est donc de savoir comment forcer les commandes du script bash à se vider, et cela dépend de ce qu'elles sont.
la source
J'ai trouvé une solution à cela ici . En utilisant l'exemple de l'OP, vous exécutez essentiellement
puis le tampon est vidé après chaque ligne de sortie. Je combine souvent cela avec
nohup
pour exécuter de longs travaux sur une machine distante.De cette façon, votre processus n'est pas annulé lorsque vous vous déconnectez.
la source
stdbuf
? Sur la base de ce commentaire, il semble qu'il ne soit pas disponible sur certaines distributions. Pourriez-vous clarifier?stdbuf
fait partie de GNU coreutils, la documentation peut être trouvée sur gnu.orgexport -f my_function
et ensuitestdbuf -oL bash -c "my_function -args"
si vous avez besoin d'exécuter une fonction au lieu d'un scriptLa clé est -f. Citation du script man:
-f, --flush Flush output after each write. This is nice for telecooperation: one person does 'mkfifo foo; script -f foo', and another can supervise real-time what is being done using 'cat foo'.
De fonctionner en arrière-plan:
la source
busybox
! (Ma coquille gèle après, mais peu importe)Vous pouvez utiliser
tee
pour écrire dans le fichier sans avoir besoin de vidage.la source
Ce n'est pas une fonction de
bash
, car le shell ne fait qu'ouvrir le fichier en question, puis passer le descripteur de fichier comme sortie standard du script. Ce que vous devez faire est de vous assurer que la sortie de votre script est supprimée plus fréquemment que vous ne le faites actuellement.En Perl par exemple, cela peut être accompli en définissant:
Voir perlvar pour plus d'informations à ce sujet.
la source
La mise en mémoire tampon de la sortie dépend de la manière dont votre programme
/homedir/MyScript
est implémenté. Si vous trouvez que la sortie est mise en mémoire tampon, vous devez la forcer dans votre implémentation. Par exemple, utilisez sys.stdout.flush () s'il s'agit d'un programme python ou utilisez fflush (stdout) s'il s'agit d'un programme C.la source
Cela aiderait-il?
tail -f access.log | stdbuf -oL cut -d ' ' -f1 | uniq
Cela affichera immédiatement les entrées uniques de access.log à l'aide de l' utilitaire stdbuf .
la source
stdbuf
disponible dans Ubuntu pour le moment, je ne sais pas où je l'ai eu.stdbuf
fait partie decoreutilus
(trouvé avecapt-file search /usr/bin/stdbuf
).À quel point le problème vient d'être repéré ici , c'est que vous devez attendre que les programmes que vous exécutez à partir de votre script terminent leur travail.
Si dans votre script vous exécutez le programme en arrière-plan, vous pouvez essayer quelque chose de plus.
En général, un appel à
sync
avant de quitter permet de vider les tampons du système de fichiers et peut aider un peu.Si dans le script vous démarrez certains programmes en arrière-plan (
&
), vous pouvez attendre qu'ils se terminent avant de quitter le script. Pour avoir une idée de son fonctionnement, vous pouvez voir ci-dessous#!/bin/bash #... some stuffs ... program_1 & # here you start a program 1 in background PID_PROGRAM_1=${!} # here you remember its PID #... some other stuffs ... program_2 & # here you start a program 2 in background wait ${!} # You wait it finish not really useful here #... some other stuffs ... daemon_1 & # We will not wait it will finish program_3 & # here you start a program 1 in background PID_PROGRAM_3=${!} # here you remember its PID #... last other stuffs ... sync wait $PID_PROGRAM_1 wait $PID_PROGRAM_3 # program 2 is just ended # ...
Puisque
wait
fonctionne avec les travaux ainsi qu'avec lesPID
nombres, une solution paresseuse devrait être de mettre à la fin du scriptfor job in `jobs -p` do wait $job done
Plus difficile est la situation si vous exécutez quelque chose qui exécute autre chose en arrière-plan car vous devez rechercher et attendre (si c'est le cas) la fin de tout le processus enfant : par exemple, si vous exécutez un démon, ce n'est probablement pas le cas attendre qu'il se termine :-).
Remarque:
wait $ {!} signifie "attendre que le dernier processus d'arrière-plan soit terminé" où
$!
est le PID du dernier processus d'arrière-plan. Donc mettrewait ${!}
juste aprèsprogram_2 &
équivaut à exécuter directementprogram_2
sans l'envoyer en tâche de fond avec&
De l'aide de
wait
:Syntax wait [n ...] Key n A process ID or a job specification
la source
Merci
@user3258569
, le script est peut-être la seule chose qui fonctionnebusybox
!La coquille a gelé pour moi après cela, cependant. En cherchant la cause, j'ai trouvé ces gros avertissements rouges "ne pas utiliser dans un shell non interactif" dans la page de manuel du script :
Vrai.
script -c "make_hay" -f /dev/null | grep "needle"
gelait la coquille pour moi.Contrairement à l'avertissement, j'ai pensé que ça
echo "make_hay" | script
passera un EOF, alors j'ai essayéecho "make_hay; exit" | script -f /dev/null | grep 'needle'
et ça a marché!
Notez les avertissements dans la page de manuel. Cela peut ne pas fonctionner pour vous.
la source
alternative à stdbuf est que
awk '{print} END {fflush()}'
je souhaite qu'il y ait un bash intégré pour faire cela. Normalement, cela ne devrait pas être nécessaire, mais avec les anciennes versions, il peut y avoir des bogues de synchronisation bash sur les descripteurs de fichiers.la source
Je ne sais pas si cela fonctionnerait, mais qu'en est-il d'appeler
sync
?la source
sync
est une opération de système de fichiers de bas niveau et n'a aucun rapport avec la sortie en mémoire tampon au niveau de l'application.sync
écrit les tampons des systèmes de fichiers sales sur le stockage physique, si nécessaire. Ceci est interne au système d'exploitation; les applications exécutées sur le système d'exploitation voient toujours une vue cohérente du système de fichiers, que les blocs de disque aient été écrits ou non sur le stockage physique. Pour la question d'origine, l'application (script) met probablement en mémoire tampon la sortie dans un tampon interne à l'application, et le système d'exploitation ne saura même pas (encore) que la sortie est en fait destinée à être écrite sur stdout. Ainsi, une opération hypothétique de type "sync" ne pourrait pas "accéder" au script et extraire les données.J'ai eu ce problème avec un processus d'arrière-plan sous Mac OS X utilisant le
StartupItems
. Voici comment je le résous:Si je fais
sudo ps aux
je peux voir quemytool
c'est lancé.J'ai trouvé que (en raison de la mise en mémoire tampon) lorsque Mac OS X s'arrête
mytool
ne transfère jamais la sortie à lased
commande. Cependant, si j'exécutesudo killall mytool
,mytool
transfère la sortie vers lased
commande. Par conséquent, j'ai ajouté unstop
cas auStartupItems
qui est exécuté lorsque Mac OS X s'arrête:start) if [ -x /sw/sbin/mytool ]; then # run the daemon ConsoleMessage "Starting mytool" (mytool | sed .... >> myfile.txt) & fi ;; stop) ConsoleMessage "Killing mytool" killall mytool ;;
la source
bien que ça plaise ou non c'est ainsi que fonctionne la redirection.
Dans votre cas, la sortie (ce qui signifie que votre script est terminé) de votre script est redirigée vers ce fichier.
Ce que vous voulez faire, c'est ajouter ces redirections dans votre script.
la source