2013-08-14 5 views
0

J'utilise Python pour exécuter un programme externe en utilisant simplement la bibliothèque « os » Python:Deux emplois bash exécutés en même temps

os.system("./script1") # script1 generates several log files and the most important for me is "info.log" ! 
os.system("./script2") # script2 uses the output from script1 

Le problème est que ces scripts sont dans l'élément 50000 « boucle » et "script1" a besoin d'au moins 2 min pour terminer son travail (il a une durée fixe) Dans les 1-2 premières secondes, je peux savoir si j'ai besoin des données de sortie ou non en regardant le "info.log" fichier. Cependant, comme "script1" est un programme déjà compilé et que je ne peux pas le modifier, je dois attendre que cela se termine.

Je pensais à une méthode Bash qui me permet de lancer deux processus en même temps: on est de commencer ./script1 et l'autre est de surveiller tout changement dans le fichier « info.log » ...
Si "info.log" a été mis à jour ou a changé de taille, le second script doit terminer les deux processus.

Quelque chose comme:

os.system("./mercury6 1 > ./energy.log 2>/dev/null & sleep 2 & if [ $(stat -c %s ./info.log) -ge 1371]; then kill %1; else echo 'OK'; fi") 

– qui ne fonctionne pas ...

S'il vous plaît, si quelqu'un connaît une méthode, laissez-moi savoir!

Répondre

-1

Voir here (Google est votre ami). Vous pouvez effectuer les tâches d'arrière-plan des processus avec le signe &, puis utiliser wait pour que le processus parent attende ses enfants.

+0

Umm no. C'est une question à propos de Python. –

+0

@OlehPrypin Il a lui-même suggéré une solution bash, je ne vois pas pourquoi une réponse bash serait invalide. – kutschkem

0
import os 
import time 

os.system("script1") 

while True: # Now this would run in 10 sec cycles and checks the output of the logs 
    try:  # And you don't have the wait the whole 2 mins to script1 to be ready 
     o = open("info.log", "r") # or add os.system("script2") here 
     # Add here more logs 
     break 
    except: 
     print "waiting script1 to be ready.." 
     time.sleep(10) # Modify (seconds) to be sufficient to script1 to be ready 
     continue 
+0

Je pense que cela terminera d'abord la ligne os.system ("script1"). Ce qui en principe n'est pas ce que je veux :( – user2681566

+0

Edité la réponse qui pourrait vous aider, si je vous ai bien compris – jester112358

+0

Je vais essayer cela aussi! Merci – user2681566

0

Je suggère d'utiliser subprocess, avec une combinaison de this answer décrivant comment tuer un script bash avec une méthode de suivi du fichier, quelque chose comme watchdog, ou une boucle de vote simple.

0

Vous pouvez essayer celui-ci. Dites-moi si script1 s'arrête pendant l'exécution afin que nous puissions essayer de le configurer davantage.

#!/bin/bash 

[ -n "$BASH_VERSION" ] || { 
    echo "You need Bash to run this script." 
    exit 1 
} 

set +o monitor ## Disable job control. 

INFO_LOG='./info.log' 

if [[ ! -f $INFO_LOG ]]; then 
    # We must create the file. 
    : > "$INFO_LOG" || { 
     echo "Unable to create $INFO_LOG." 
     exit 1 
    } 
fi 

read FIRSTTIMESTAMP < <(stat -c '%s' "$INFO_LOG") && [[ $FIRSTTIMESTAMP == +([[:digit:]]) ]] || { 
    echo "Unable to get stat of $INFO_LOG." 
    exit 1 
} 

# Run the first process with the script. 

./script1 & 
SCRIPT1_PID=$! 
disown "$SCRIPT1_PID" 

# Run the second process. 

(
    function kill_processes { 
     echo "Killing both processes." 
     kill "$SCRIPT1_PID" 
     exit 1 
    } 

    [[ -f $INFO_LOG ]] || { 
     echo "File has been deleted." 
     kill_processes 
    } 

    read NEWTIMESTAMP < <(stat -c '%s' "$INFO_LOG") && [[ $NEWTIMESTAMP == +([[:digit:]]) ]] || { 
     echo "Unable to get new timestamp of $INFO_LOG." 
     kill_processes 
    } 

    [[ NEWTIMESTAMP -ne FIRSTTIMESTAMP ]] || { 
     echo "$INFO_LOG has changed." 
     kill_processes 
    } 

    sleep 4s 
) & 

disown "$!" 

Vous pouvez également consulter d'autres solutions similaires ici: linux script with netcat stops working after x hours


(
    function kill_processes { 
     echo "Killing both processes." 
     kill "$mercury6_PID" 
     exit 1 
    } 
    while IFS= read -r LINE; do 
     [[ "${LINE}" == "ejected" ]] && { ## Perhaps it should be == *ejected* ? 
      echo "$INFO_LOG has changed." 
      kill_processes 
     } 
    done < <(tail -f "$INFO_LOG") 
) & 

disown "$!" 
+0

:) Merci! Je pense que ça va marcher !!! cependant il y a une petite complication .. il s'avère que le fichier change une fois avant le script mercure pour commencer à donner des informations .... ./monitor_mercury: ligne 58: désavouer: 0: pas un tel travail Intégrer des corps massifs et des particules jusqu'à la même époque. Début de l'intégration principale. - ici après cette ligne est important ou pouvons-nous le faire pour lire le fichier et s'il y a une chaîne "AINNER" ou "BOUTER" pour arrêter le script? – user2681566

+0

À propos de 'disown 0', le problème était en fait parce que j'ai utilisé' $? '. Cela aurait dû être '$!': 'Désavouer" $! "'. J'ai fait la correction. Nous pouvons peut-être, mais seulement si le fichier n'est pas verrouillé à partir de l'accès en lecture pendant que script1 est en cours d'exécution. Pouvez-vous vérifier si c'est encore lisible? Donc, en fait, nous ne baserions plus sur l'horodatage du fichier et seulement sur les chaînes de caractères? Vous pouvez cependant attendre quelques secondes pour laisser le script Mercury pendant un moment et commencer à enregistrer les horodatages par la suite. – konsolebox

+0

ce n'est pas verrouillé! J'ouvre fréquemment ce journal lorsque je commence de longs calculs. – user2681566

0

Il a été fait! pas si élégant mais ça marche! c'est le code:

#/bin/bash

[-n ​​"$ BASH_VERSION"] || { echo "Vous avez besoin de Bash pour exécuter ce script." exit 1 }

# set + o moniteur ## Désactiver le contrôle du travail.

INFO_LOG = "./ info.out"

# Exécutez le premier processus avec le script.

./mercury6 1> ./energy.log 2>/dev/null & mercury6_PID = $! désinscription "$ mercury6_PID"

# Exécutez le deuxième processus.

( sommeil 5 KILL_PROCESSES fonction { echo kill "$ mercury6_PID" de sortie 1 "Tuer les deux processus."} alors IFS = lire -r, faire
[[ « $ {LINE} "== "éjecté"]] || [[ "$ {LINE}" == "complète".]] & & { echo "$ INFO_LOG a changé." queue killall KILL_PROCESSES } fait < < (tail -f "$ INFO_LOG") )

# &

#disown "$!"

Si vous avez des recommandations, vous êtes les bienvenus! BTW Je vais essayer de le faire avec os.fork() en python ainsi. Merci encore!