Bash linux 强制多个实例等待 运行 sqlplus 命令完成
Bash linux force multiple instances to wait for running sqlplus command to finish
我有一个 bash 脚本,可以同时允许多个 运行 实例。但是,有一个到 Oracle 数据库的 sqlplus 连接来检索值。如果多个 bash 脚本实例同时获取此值,它们可能会检索到相同的值,因为当第一个实例仍在处理时,第二个实例已经在验证 'old data'.
我只能想到两个选项,一个是用PIDFILE锁定函数。缺点是如果用户在删除 pid 文件之前中止操作,则会导致问题。另一个是基于声明用 ps -ef | grep 'scriptname' | wc -l
计数的最大进程来锁定整个脚本。但这会锁定整个脚本,而不仅仅是数据库部分。
那么还有其他选择吗?这个与数据库的 sqlplus 连接是否有可能以某种方式捕获,以便我可以在其中一个实例执行此函数时暂停多个 运行 实例?
您可以在 tmp 文件中使用唯一值(/tmp/pidfile
对于本例),并在脚本中止或完成时重置它。
更新:这看起来很可靠,请参阅底部的测试。
#!/bin/bash
bashpid="$$" # Records PID of script. Unused so far
pidfile=/tmp/pidfile # pidfile var
pidlimit=2 # pidlimit
cleanup () { # cleanup operations
exit
}
pidreset () { # trap operations (if reqd)
pkill -a -P "$bashpid"
kill -9 0
}
trap "pidreset" SIGINT # trap (if reqd)
countpid () { # This is the true PID count, only called
# Once allowed in the database block
# This includes self instance
ps aux | grep "$(basename [=10=])" | grep -v grep > $pidfile
}
countloop () { # This counts PID while waiting for a spot
# (-1 decrement since self is included but
# not yet granted access to database block)
echo "(( ("$(ps aux | grep "$(basename [=10=])" | grep -v grep | wc -l )") - 1))" | bc > $pidfile
}
databasecall () { # The database script calls
touch $pidfile
pidcount="$(cat $pidfile | wc -l)"
until [[ "$pidcount" -le "$pidlimit" ]]; do
echo "too many processes"
countloop
pidcount="$(cat $pidfile | wc -l)"
sleep 5
done
# ================ Start of Database access Code ================
# Go ahead and do database stuff
# Write this script into the pidfile incrementing its count also
countpid
pidcount="$(cat $pidfile | wc -l)"
echo "We're in"
echo "Scriptcount: $pidcount (Including this one)"
sleep 5
cleanup
# return / whatever
# ================ End of Database access Code ================
}
echo "Main script block" # Main script outside of Database block
sleep .1
databasecall # Call database function
cleanup # Call to housekeeping
测试
它工作正常但稳定在 运行 比 pidlimit 多一个,虽然我不确定这是在哪里发生的或者它是否是我的测试场景。
bash>echo "imrunning & sleep .5 ; imrunning & sleep .5 ; imrunning & sleep .5 ; imrunning & sleep .5 ; imrunning" > /tmp/initrunning ; chmod +x /tmp/initrunning
bash>/tmp/./initrunning
Main script block
We're in
Scriptcount: 1 (Including this one)
Main script block
We're in
Scriptcount: 2 (Including this one)
Main script block
too many processes
Main script block
too many processes
Main script block
too many processes
We're in
Scriptcount: 3 (Including this one)
We're in
Scriptcount: 3 (Including this one)
We're in
Scriptcount: 3 (Including this one)
bash
我有一个 bash 脚本,可以同时允许多个 运行 实例。但是,有一个到 Oracle 数据库的 sqlplus 连接来检索值。如果多个 bash 脚本实例同时获取此值,它们可能会检索到相同的值,因为当第一个实例仍在处理时,第二个实例已经在验证 'old data'.
我只能想到两个选项,一个是用PIDFILE锁定函数。缺点是如果用户在删除 pid 文件之前中止操作,则会导致问题。另一个是基于声明用 ps -ef | grep 'scriptname' | wc -l
计数的最大进程来锁定整个脚本。但这会锁定整个脚本,而不仅仅是数据库部分。
那么还有其他选择吗?这个与数据库的 sqlplus 连接是否有可能以某种方式捕获,以便我可以在其中一个实例执行此函数时暂停多个 运行 实例?
您可以在 tmp 文件中使用唯一值(/tmp/pidfile
对于本例),并在脚本中止或完成时重置它。
更新:这看起来很可靠,请参阅底部的测试。
#!/bin/bash
bashpid="$$" # Records PID of script. Unused so far
pidfile=/tmp/pidfile # pidfile var
pidlimit=2 # pidlimit
cleanup () { # cleanup operations
exit
}
pidreset () { # trap operations (if reqd)
pkill -a -P "$bashpid"
kill -9 0
}
trap "pidreset" SIGINT # trap (if reqd)
countpid () { # This is the true PID count, only called
# Once allowed in the database block
# This includes self instance
ps aux | grep "$(basename [=10=])" | grep -v grep > $pidfile
}
countloop () { # This counts PID while waiting for a spot
# (-1 decrement since self is included but
# not yet granted access to database block)
echo "(( ("$(ps aux | grep "$(basename [=10=])" | grep -v grep | wc -l )") - 1))" | bc > $pidfile
}
databasecall () { # The database script calls
touch $pidfile
pidcount="$(cat $pidfile | wc -l)"
until [[ "$pidcount" -le "$pidlimit" ]]; do
echo "too many processes"
countloop
pidcount="$(cat $pidfile | wc -l)"
sleep 5
done
# ================ Start of Database access Code ================
# Go ahead and do database stuff
# Write this script into the pidfile incrementing its count also
countpid
pidcount="$(cat $pidfile | wc -l)"
echo "We're in"
echo "Scriptcount: $pidcount (Including this one)"
sleep 5
cleanup
# return / whatever
# ================ End of Database access Code ================
}
echo "Main script block" # Main script outside of Database block
sleep .1
databasecall # Call database function
cleanup # Call to housekeeping
测试
它工作正常但稳定在 运行 比 pidlimit 多一个,虽然我不确定这是在哪里发生的或者它是否是我的测试场景。
bash>echo "imrunning & sleep .5 ; imrunning & sleep .5 ; imrunning & sleep .5 ; imrunning & sleep .5 ; imrunning" > /tmp/initrunning ; chmod +x /tmp/initrunning bash>/tmp/./initrunning Main script block We're in Scriptcount: 1 (Including this one) Main script block We're in Scriptcount: 2 (Including this one) Main script block too many processes Main script block too many processes Main script block too many processes We're in Scriptcount: 3 (Including this one) We're in Scriptcount: 3 (Including this one) We're in Scriptcount: 3 (Including this one) bash