2017-10-13 3 views
1

Ich möchte mehrere Instanzen simultan synchronisieren/"sequenzialisieren", die gleichzeitig von einer bestimmten Shell ausgeführt werden.So synchronisieren Sie verschiedene Shell-Instanzen

Optional kann eine Teilmenge von Argumenten bestimmen, ob der Prozess sofort ausgeführt werden kann oder warten muss.

Um klar zu sein:

Wenn ich laufen die folgenden drei Befehle gleichzeitig (in diesem Beispiel schema und table Option bestimmen das Schloss):

loadTable --schema dev --table person --file mydata1.txt 
loadTable --schema dev --table person --file mydata2.txt 
loadTable --schema dev --table enterprise --file mydata3.txt 

Ich möchte:

  • die erste und dritte Befehle gleichzeitig ausgeführt werden können
    da partielle Argumente unterschiedlich sind (schema und table)
  • der zweite Befehl das Ende der einen
    ersten warten muss, weil teilweise Argumente identisch sind (schema und table)

Für mich 2 Lösungen :

  • Die loadTable-Shell muss selbst eine Warteschlange verwalten.
  • ein Elternteil Proxy Shell muss

verwalten ich einige Ideen, aber es scheint ein wenig komplex ...

Danke für Ihre Hilfe

Antwort

0

Wenn ich es richtig , müssen Sie so etwas wie dies zu tun:

loadTable --schema dev --table person --file mydata1.txt & 
loadTable --schema dev --table enterprise --file mydata3.txt & 
wait %1 && loadTable --schema dev --table person --file mydata2.txt & 
wait 

in diesem Fall werden Sie Befehle 1 und 3 in paralle laufen l, dann warte erst der erste Befehl, um den zweiten zu beenden. Danach warten Sie alle von ihnen zu beenden

+0

Danke für die Idee, aber ich weiß nicht im Voraus die Befehle gestartet – Indent

1

Ich habe eine synchronisieren Funktion gemacht.

Ich kann jetzt einfach am Anfang meines Skript aufrufen (nach args Parsen):

synchronize $myTable-$mySchema 

Es macht den Job, aber wir können es vielleicht vereinfacht.

Code:

function synchronize() { 
    key=${1:-noKey};  
    shell_fullname=$(readlink -f $0) 
    shell_basename=$(basename $shell_fullname)  
    hash=$(echo "${shell_fullname}-${key}" | md5sum | cut -b-32) 
    delay=2 
    pid_file=/tmp/${shell_basename}.${hash}.pid  
    current_pid=$$   

    echo "synchronize$shell_basename($key)" 
    ( 
     # First step : lock file   
     isUnLock=true 
     echo "trying to acquire lock" 
     while $isUnLock 
     do 
      # Wait for lock on file desciptor 200 for 10 seconds 
      flock -x -w $delay 200 && isUnLock=false 
      $isUnLock && echo "Waiting lock for"     
     done 

     # here : isUnLock must normally be false 
     $isUnLock && echo "unable to acquire lock" # not possible for me 
     $isUnLock && exit 255 # bad luck... 
     $isUnLock || echo "lock OK"   

     # Second step : waiting eventual previous process 
     while [ -e ${pid_file} ] && kill -0 `cat $pid_file` > /dev/null 2>&1 
     do 
      echo "Another process already running with process_id $(cat ${pid_file})"   
      sleep $delay 
     done 

     # here : previous shell stop and the current process has lock the pid_file 
     echo $current_pid > ${pid_file} 

     # now we can unlock the pid file and the current shell can be running alone safely 
     # (just fail if somebody delete the pid_file...)   

    ) 200>$pid_file.lock # add suffix, flock seems make empty file after lock... 

} 

key=$1 # construct key using args 
synchronize$key 

ligthest Version

function synchronize() { 
    key=${1:-noKey};  
    shell_fullname=$(readlink -f $0) 
    shell_basename=$(basename $shell_fullname)  
    hash=$(echo "${shell_fullname}-${key}" | md5sum | cut -b-32) 
    delay=10 
    pid_file=/tmp/${shell_basename}.${hash}.pid  
    current_pid=$$   

    echo "synchronize $shell_basename($key) pid_file=$pid_file" 
    ( 
     # First step : lock file, Wait for lock on file desciptor 200 
     echo "trying to acquire lock" 
     flock -x 200 
     echo "lock acquired" 

     # Second step : waiting eventual previous process   
     [ -s $pid_file ] && previous_pid=$(cat $pid_file) || previous_pid=00 # 00 is an impossible pid   
     [ -e /proc/${previous_pid} ] && echo "Another process already running with process_id $previous_pid"   
     while [ -e /proc/${previous_pid} ]; do sleep $delay; done 

     # here : previous shell is stop and the current process has lock the pid_file   
     echo $current_pid > ${pid_file}   
     echo "current pid $current_pid is running" 

     # now we can unlock the pid file and the current shell can be running several minutes  

    ) 200>$pid_file.lock # add suffix, flock seems make empty file after lock... 

} 
1

Sie können ein wenig den zweiten Schritt vereinfachen und Sécurisé
(securise => auf diese Weise funktioniert es auch, wenn $pid_file löschen ist während der vorherigen Ausführung)

# Second step : waiting eventual previous process 
previous_pid=$(cat $pid_file) 
previous_pid=${previous_pid:00} # 00 is an impossible pid 
while [ -e /proc/${previous_pid} ] 
do 
    echo "Another process already running with process_id ${previous_pid}"   
    sleep $delay 
done 
Verwandte Themen