Bash 如何同步不同的shell实例

Bash 如何同步不同的shell实例,bash,unix,parallel-processing,synchronization,locking,Bash,Unix,Parallel Processing,Synchronization,Locking,我想同步/顺序化同时运行特定shell的多个实例 或者,参数子集可以确定进程是否可以立即运行或必须等待 要明确的是: 如果同时运行以下三个命令(在本例中,schema和table选项确定锁): 我想: 第一个和第三个命令可以同时运行 因为部分参数不同(schema和table) 第二个命令必须等待第一个命令的结束 因为部分参数是相同的(schema和table) 对于me 2解决方案: loadTable shell必须自己管理等待队列 父代理shell必须管理它 我有一些想法,但似乎有

我想同步/顺序化同时运行特定shell的多个实例

或者,参数子集可以确定进程是否可以立即运行或必须等待

要明确的是:

如果同时运行以下三个命令(在本例中,
schema
table
选项确定锁):

我想:

  • 第一个第三个命令可以同时运行
    因为部分参数不同(
    schema
    table
  • 第二个命令必须等待第一个命令的结束
    因为部分参数是相同的(
    schema
    table
对于me 2解决方案:

  • loadTable shell必须自己管理等待队列
  • 父代理shell必须管理它
我有一些想法,但似乎有点复杂


谢谢你的帮助

如果我没弄错,你需要做以下事情:

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

在本例中,您将并行运行命令1和3,然后等待第一个命令完成并运行第二个命令。在那之后,您等待所有这些操作完成

我制作了一个同步功能

现在,我只需在脚本开头调用(在args解析之后):

它确实起作用,但我们或许可以简化它

代码:

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
最轻版本

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... 

}

您可以在第二步中稍微简化和安全化
(securise=>通过这种方式,即使在上一次执行期间删除了
$pid_file
,它也可以工作)


谢谢你的主意,但我事先不知道启动了什么命令
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
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... 

}
# 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