如何在后台运行bourne shell函数

时间:2013-04-25 17:54:12

标签: function parallel-processing sh

在这种情况下,我有一个由其他人写的可执行文件随机死亡,解决它的方法是重新启动该作业最多3次(总共4次)。我还需要并行运行具有不同输入的可执行文件的6个副本。可执行文件也可能需要数小时才能运行。可执行文件是通过bourne shell脚本运行的(不是bash,由于遗留原因,我无法切换到bash或其他shell)。目前,bourne shell脚本同时启动6次运行,等待所有这些运行完成或死亡,然后重新启动任何已经死亡,并等待所有它们完成或死亡,然后重新启动任何已经死亡的时间等等。

我有一个想法是在bourne shell脚本中编写一个函数,启动6个运行中的1个等待它完成或死亡,如果它死了,重新启动那个运行立即运行,while循环调用启动/重新启动功能与&使它在后台运行并在while循环结束后等待,以使其等待启动 - 重启功能的所有并行执行完成,然后并行继续执行其余脚本。

这没有达到预期的效果。它似乎在后台并行运行启动/重启功能的所有副本,但是while循环结束时的等待不会延迟脚本其余部分的执行,因为逻辑检查了它由可执行文件生成的文件。

有些人可以通过提供一个示例脚本来帮助我,该脚本如何并行启动6个可执行文件,并且每个可执行文件在完成后重新启动3次,假设可执行文件采用一个命令行参数来指示名称要读入的输入文件和要写出的输出文件的名称。

由于

编辑: 这是一个模拟的executable.cpp文件

#include <ctime>
#include <cstdlib> //for abort()
#include <cstring> //for strcmp()
#include <iostream>
#include <fstream>
#include <sstream>

int main (int argc, char *argv[])
{ 
  if(argc < 2) {
    //give instructions
    std::cout << "this function requires 1 argument, a process id.\n"
          << "If the optional second command argument has the\n"
          << "value \"die\" the run will die prematurely." << std::endl;
    return 1;
  }else if(argc>=3) {
    //to test the script we need to give this executable the ability to
    //die on command
    if(strcmp(argv[2],"die")==0) abort();
  }

  time_t t0; //start time
  time_t tc; //current time
  double seconds; //seconds between current time and start time

  time(&t0); //assign value of the start time
  do{
    time(&tc); //assign value of the current time
    seconds=difftime(tc,t0); //compute the time difference in seconds
  } while(seconds<10); //wait until 10 seconds have passed.

  std::ostringstream oss;
  oss << "proc_" << argv[1] << ".output";
  std::ofstream ofs;
  ofs.open(oss.str().c_str(),std::ofstream::out);
  ofs << "this run completed" << std::endl;
  ofs.close();

  return 0;
}

这是一个模拟运行脚本.sh文件

#! /bin/sh -ha
executable_name=$1

#---------------------------------------------------------------------
launch_relaunch_func() {
#---------------------------------------------------------------------
    process_num=$1
    first_attempt_to_not_die=$process_num

    if_my_proc_completed_successfully="no"
    num_attempts_for_my_proc_so_far=0
    max_attempts=4
    second_arg="die"
    output_fname="proc_${process_num}.output"

    while [ "if_my_proc_completed_successfully" = "no" -a \
    ${num_attempts_for_my_proc_so_far} -lt ${max_attempts} ]; do

    num_attempts_for_my_proc_so_far=`expr "${num_attempts_for_my_proc_so_far} + 1"`
    if [ ${num_attempts_for_my_proc_so_far} -ge ${first_attempt_to_not_die} ] ; then
        second_arg="live"
    fi

    ./${executable_name} ${process_num} ${second_arg}

    if [ -s ${output_fname} ] ; then
        if_my_proc_completed_successfully="yes"
    fi
    done

    if [ "if_my_proc_completed_successfully" = "no" ] ; then
    echo "process ${proc_num} failed on all ${max_attempts} attempts"
    echo ${proc_num} >> bad_runs.txt
    return 1
    fi

    echo ${proc_num} >> good_runs.txt
    return 0;
}
#---------------------------------------------------------------------

proc_list="1 2 3 4"
num_procs=4;
for proc in ${proc_list} ; do
    (launch_relaunch_func $proc) &
done 
wait

if [ `ls -1 proc_[0-9].output 2>/dev/null | wc -l` -eq $num_procs ] ; then
    echo "all runs completed successfully"
    rm -f good_runs.txt bad_runs.txt
else
    printf "Success: %d Failed: %d\n" `wc -l good_runs.txt | cut -d \  -f 1` `wc -l bad_runs.txt | cut -d \  -f 1`
    exit 2
fi
exit 0

感谢

0 个答案:

没有答案