我需要创建一个shell脚本,根据从目录/dir1/dir2/flag_file_directory
中的shell脚本收到的请求标志和目录中的源文件,将一些指示符/标志文件放在一个名为/dir1/dir2/req_flag_file_directory
的目录中。目录说dir1/dir2/source_file_directory
。为此,我需要在无限循环中使用 while
条件运行脚本,因为我不知道源文件何时可用。
所以,我的实施计划有点像这样 - 假设 JOB1 计划在早上的某个时间运行将首先(触摸)请求标志(例如,touch / dir1 / dir2 / req_flag_file_directory / req1.req),表示此作业正在运行,因此查找源文件目录中存在的模式file_pattern_YYYYMMDD.CSV
的源文件(不同作业的文件模式不同),如果它们存在,然后计算数字。如果文件计数正确,则首先删除此作业的请求标志,然后touch
/dir1/dir2/flag_file_directory
中的指示符/标志文件。然后,此指标/标志文件将用作指示源文件全部存在,并且可以继续作业将这些文件加载到我们的系统中。
我将把有关作业及其标志文件的所有细节都放在一个文件中,其结构如下所示。根据请求标志,脚本应该在放置指标文件之前知道它应该寻找的其他标准:
request_flags|source_name|job_name|file_pattern|file_count|indicator_flag_file
req1.req|Sourcename1|jobname1|file_pattern_1|3|ind1.ind
req2.req|Sourcename2|jobname2|file_pattern_2|6|ind2.ind
req3.req|Sourcename3|jobname3|file_pattern_3|1|ind3.ind
req**n**.req|Sourcename**n**|jobname**n**|file_pattern_**n**|2|ind**n**.ind
如果您有其他建议或解决方案,请告诉我如何实现这一目标
答案 0 :(得分:2)
而是让服务守护程序脚本在无限循环中轮询(即定期唤醒以检查它是否需要工作),您可以使用文件锁定和命名管道来创建事件队列。
服务守护程序概述daemon.sh
。这个脚本将无限循环,通过从read line
的命名管道读取来阻塞,直到消息到达(即,其他一些进程写入$RequestPipe
)。
#!/bin/bash
# daemon.sh
LockDir="/dir1/dir2/req_flag_file_directory"
LockFile="${LockDir}/.MultipleWriterLock"
RequestPipe="${LockDir}/.RequestQueue"
while true ; do
if read line < "$RequestPipe" ; then
# ... commands to be executed after message received ...
echo "$line" # for example
fi
done
requestor.sh
的大纲,该脚本在一切准备就绪时唤醒服务守护程序。该脚本完成了所有必要的准备工作,例如在req_flag_file_directory
和source_file_directory
中创建文件,然后通过写入命名管道唤醒服务守护程序脚本。它甚至可以发送一条消息,其中包含服务守护程序的更多信息,例如&#34;作业1就绪&#34;。
#!/bin/bash
# requestor.sh
LockDir="/dir1/dir2/req_flag_file_directory"
LockFile="${LockDir}/.MultipleWriterLock"
RequestPipe="${LockDir}/.RequestQueue"
# ... create all the necessary files ...
(
flock --exclusive 200
# Unblock the service daemon/listener by sending a line of text.
echo Wake up sleepyhead. > "$RequestPipe"
) 200>"$LockFile" # subshell exit releases lock automatically
daemon.sh
充实了一些错误处理:
#!/bin/bash
# daemon.sh
LockDir="/dir1/dir2/req_flag_file_directory"
LockFile="${LockDir}/.MultipleWriterLock"
RequestPipe="${LockDir}/.RequestQueue"
SharedGroup=$(echo need to put a group here 1>&2; exit 1)
#
if [[ ! -w "$RequestPipe" ]] ; then
# Handle 1st time. Or fix a problem.
mkfifo --mode=775 "$RequestPipe"
chgrp "$SharedGroup" "$RequestPipe"
if [[ ! -w "$RequestPipe" ]] ; then
echo "ERROR: request queue, can't write to $RequestPipe" 1>&2
exit 1
fi
fi
while true ; do
if read line < "$RequestPipe" ; then
# ... commands to be executed after message received ...
echo "$line" # for example
fi
done
requestor.sh
充实了一些错误处理:
#!/bin/bash
# requestor.sh
LockDir="/dir1/dir2/req_flag_file_directory"
LockFile="${LockDir}/.MultipleWriterLock"
RequestPipe="${LockDir}/.RequestQueue"
SharedGroup=$(echo need to put a group here 1>&2; exit 1)
# ... create all the necessary files ...
#
if [[ ! -w "$LockFile" ]] ; then
# Handle 1st time. Or fix a problem.
touch "$LockFile"
chgrp "$SharedGroup" "$LockFile"
chmod 775 "$LockFile"
if [[ ! -w "$LockFile" ]] ; then
echo "ERROR: write lock, can't write to $LockFile" 1>&2
exit 1
fi
fi
if [[ ! -w "$RequestPipe" ]] ; then
# Handle 1st time. Or fix a problem.
mkfifo --mode=775 "$RequestPipe"
chgrp "$SharedGroup" "$RequestPipe"
if [[ ! -w "$RequestPipe" ]] ; then
echo "ERROR: request queue, can't write to $RequestPipe" 1>&2
exit 1
fi
fi
(
flock --exclusive 200 || {
echo "ERROR: write lock, $LockFile flock failed." 1>&2
exit 1
}
# Unblock the service daemon/listener by sending a line of text.
echo Wake up sleepyhead. > "$RequestPipe"
) 200> "$LockFile" # subshell exit releases lock automatically
答案 1 :(得分:1)
对请求文件的内容仍有疑问,但我想我已经提出了一个相当简单的解决方案:
#!/bin/bash
DETAILS_FILE="details.txt"
DETAILS_LINES=$((`wc -l $DETAILS_FILE|awk '{print $1}'`-1)) # to remove banner line (first line)
DETAILS=`tail -$DETAILS_LINES $DETAILS_FILE|tr '\n\r' ' '`
PIDS=()
IFS=' '
waitall () { # PIDS...
## Wait for children to exit and indicate whether all exited with 0 status.
local errors=0
while :; do
debug "Processes remaining: $*"
for pid in $@; do
echo "PID: $pid"
shift
if kill -0 "$pid" 2>/dev/null; then
debug "$pid is still alive."
set -- "$@" "$pid"
elif wait "$pid"; then
debug "$pid exited with zero exit status."
else
debug "$pid exited with non-zero exit status."
((++errors))
fi
done
(("$#" > 0)) || break
# TODO: how to interrupt this sleep when a child terminates?
sleep ${WAITALL_DELAY:-1}
done
((errors == 0))
}
debug () { echo "DEBUG: $*" >&2; }
#function to check for # of sourcefiles matching pattern in dir
#params: req3.req Sourcename3 jobname3 file_pattern_3 1 ind3.ind
check () {
NOFILES=`find $2 -type f | egrep -c $4`
if [ $NOFILES -eq "$5" ];then
echo "Touching file $6. done."
touch $6
else
echo "$NOFILES matching $4 pattern. exiting"
fi
}
echo "parsing $DETAILS_FILE file..."
read -a lines <<< "$DETAILS"
for line in "${lines[@]}"
do
IFS='|'
read -a ARRAY <<< "$line"
echo "Line processed. Dispatching job ${ARRAY[2]}..."
check ${ARRAY[@]} &
IFS=' '
PIDS="$PIDS $!"
#echo $PIDS
done
waitall ${PIDS}
wait
虽然不完全处于无限循环中。此脚本旨在在crontab中运行。
首先,根据您的示例,它会读取details.txt
文件。
解析所有细节后,此脚本将调度check
函数,其唯一目的是计算与每个file_pattern
文件夹source_name
匹配的文件数,如果文件数为等于file_count
,然后触及indicator_flag_file
。
希望有所帮助!