【发布时间】:2014-10-07 21:27:36
【问题描述】:
编辑:我在这里简化我的问题:BASH local and flock
我设法创建了一个启动后台进程的管理器。 目的是:
- 启动管理器并仅启动 nb_min(示例 1)子进程(本示例中为 python 文件)。
- 如果子进程以 0 错误代码结束,则升级到 nb_max(示例 10)子进程
- 否则仅重新启动 nb_min (1) 进程
所以我只会在 nb_min 和 nb_max 之间同时启动子进程
现在,我想为每次启动添加一个 id 插槽,以确保我只有 1 个使用相同 id_slot 运行的调用...我不知道如何管理这个!
这里是 manager.sh 代码:
#!/bin/bash
if [ "$USER" != "root" ]
then
echo "erreur"
echo "il faut lancer ce script en root"
echo "sudo $0 nb_jobs_depart nb_jobs_max command"
exit 1
fi
if [[ $# < 3 ]]
then
echo "erreur"
echo "il faut au moins 3 parametres"
echo "sudo $0 nb_jobs_depart nb_jobs_max command"
exit 1
fi
min_jobs=$1
shift
max_jobs=$1
shift
command=$@
#n_job=$min_job
echo $min_jobs>/dev/shm/n_job
function _job_worker()
{
local command=$@
local result=
echo "lancement de $command"
#{ $command ; } >>./_logme.log 2>&1
$command >>./_logme.log 2>&1
local result=$?
echo "retour de command : $result"
if [[ "${result}" == "0" ]]; then
echo $max_jobs>/dev/shm/n_job
#n_job=$max_jobs
echo "passage a $max_jobs jobs"
else
echo $min_jobs>/dev/shm/n_job
#n_job=$min_jobs
echo "passage a $min_jobs jobs"
fi
}
while true; do
n_job=$(</dev/shm/n_job)
current_jobs=$(jobs -pr)
x=0;
for job in $current_jobs; do
(( x++ ))
done;
echo "il y a $x jobs en cours, il en faut $n_job"
jobs_to_run=$(($n_job - $x))
if (( jobs_to_run > 0 )); then
echo "il y a $jobs_to_run a relancer"
for (( y = 0; y < $jobs_to_run; y++ )); do
_job_worker $command &
done
fi
x=0
echo "petite pause"
jobs
sleep 1
done
这是用于测试的 python 代码,使用 2 个参数调用:
- 几秒钟后暂停
- 退出代码
示例:./sleeper.pl 10 0 启动 10 秒的暂停并返回错误代码 0
#!/usr/bin/perl -w
use strict;
my $time = $ARGV[0] || 1;
my $exit = $ARGV[1] || 0;
print "bonjour $time $exit \n";
sleep $time;
exit $exit;
现在是代码示例:
./manager.sh 1 10 ./sleeper.pl 10 0
- 如果错误码 == 0,则调用最少 1 个进程,最多 10 个进程
- 每个进程调用 sleeper.pl,暂停 10 秒,返回码为 0
编辑:16h30
我试图从这里管理共享数组建议:bash background process modify global variable
但是后来被锁的问题撞到了,女巫我试图用羊群覆盖,但后来我松开了锁和之后的 z 局部变量......
这个新版本尝试使用每个孩子的 pid ...但现在我总是得到相同的 PID ...????....
#!/bin/bash
if [ "$USER" != "root" ]
then
echo "erreur"
echo "il faut lancer ce script en root"
echo "sudo $0 nb_jobs_depart nb_jobs_max command"
exit 1
fi
if [[ $# < 3 ]]
then
echo "erreur"
echo "il faut au moins 3 parametres"
echo "sudo $0 nb_jobs_depart nb_jobs_max command"
exit 1
fi
min_jobs=$1
shift
max_jobs=$1
shift
command=$@
#n_job=$min_job
echo $min_jobs>/dev/shm/n_job
declare -A SLOTS
for (( y = 1; y <= $min_jobs; y++ )); do
SLOTS[$y]="vide"
done
set | grep ^SLOTS= >/dev/shm/SLOTS
declare -A PIDS
exists(){
if [ "$2" != in ]; then
echo "Incorrect usage."
echo "Correct usage: exists {key} in {array}"
return
fi
eval '[ ${'$3'[$1]+muahaha} ]'
}
function _job_worker()
{
local command=$@
local z=1
local result=
# je dois trouver un slot dispo
echo "avant le lock mon pid vaut $$"
(
# Wait for lock on /var/lock/.manager.exclusivelock (fd 200)
flock -x -w 10 200 || return
echo "apres le lock mon pid vaut $$"
declare -A SLOTS;
. /dev/shm/SLOTS
echo "DEBUG etat des slots AVANT process"
dumpSLOTS
for i in "${!SLOTS[@]}"
do
if [[ "${SLOTS[$i]}" != "vide" ]];
then
z=$(( $z + 1 ))
echo "z vaut $z"
if [[ $z -gt $n_job ]]; then
echo "ERREUR tous les slots sont plein ...."
exit 9
fi
fi
done
echo "je remplie le slot $z avec le pid $$"
SLOTS[$z]=$$
PIDS[$$]=$z
# je sauve
set | grep ^SLOTS= >/dev/shm/SLOTS
) 200>/var/lock/.manager.exclusivelock
echo "mon pid est $$ je cherche le slot qui correspond"
local my_slot=$PIDS[$$]
echo "lancement de $command sur le slot $my_slot"
$command $my_slot >>./_logme.log 2>&1
result=$?
# je recharge la liste des slots
. /dev/shm/SLOTS
echo "retour de command : $result"
if [[ "${result}" == "0" ]]; then
echo $max_jobs>/dev/shm/n_job
#n_job=$max_jobs
echo "passage a $max_jobs jobs"
for (( y = 1; y <= $max_jobs; y++ )); do
#if ! exists $y in $SLOTS; then SLOTS[$y]="vide"; fi
if [ ! ${SLOTS[$y]+existe} ] ;
then
SLOTS[$y]="vide";
fi
done
else
echo $min_jobs>/dev/shm/n_job
#n_job=$min_jobs
echo "passage a $min_jobs jobs"
fi
# je vide le slot
SLOTS[$my_slot]="vide"
# je sauve
(
# Wait for lock on /var/lock/.manager.exclusivelock (fd 200)
flock -x -w 10 200 || return
# je sauve
set | grep ^SLOTS= >/dev/shm/SLOTS
) 200>/var/lock/.manager.exclusivelock
echo "etat des slots APRES process"
dumpSLOTS
sleep .3;
}
function dumpSLOTS() {
declare -A SLOTS;
. /dev/shm/SLOTS
printf "%12s" ${!SLOTS[@]}
echo
printf "%12s" ${SLOTS[@]}
echo
}
while true; do
echo "le pid du process pere est $$"
n_job=$(</dev/shm/n_job)
current_jobs=$(jobs -pr)
x=0;
for job in $current_jobs; do
(( x++ ))
done;
echo "il y a $x jobs en cours, il en faut $n_job"
jobs_to_run=$(($n_job - $x))
if (( jobs_to_run > 0 )); then
echo "il y a $jobs_to_run a relancer"
for (( y = 0; y < $jobs_to_run; y++ )); do
echo " je lance"
_job_worker $command & 2>&1 | tee
done
fi
x=0
echo "etat des jobs"
jobs
echo "etat des slots"
dumpSLOTS
echo "etat des PIDS"
printf "%12s" ${!PIDS[@]}
echo
printf "%12s" ${PIDS[@]}
echo
sleep 1
done
【问题讨论】:
标签: bash background subprocess slot