如何在不破坏输出的情况下并行运行 shell 中的命令?

如何在不破坏输出的情况下并行运行 shell 中的命令?

我有以下脚本:

./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 1 0 10 0.1 &
./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 1 0 10 0.2 &
./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 1 0 10 0.5 &
./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 1 0 10 1 &
./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 1 0 25 0.1 &
./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 1 0 25 0.2 &
./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 1 0 25 0.5 &
./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 1 0 25 1 &
./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 2 0 10 0.1 &
./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 2 0 10 0.2 &
./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 2 0 10 0.5 &
./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 2 0 10 1 

我的主要功能具有如下结构:

int main(int argc, char** argv)
{
    if(argc<18)
    {
        cout<<"Insufficient parameters"<<endl;
        cout<<"loop #ofGen popSize chrLen Pc PmNumerator randPopRate BOAimmigrantsRate Pn algoType #ofBOAsamples mkpfileNo noiseType prb env per sev"<<endl;
        exit(1);
    }

    int algoType;// GA or PBIL
    int mkpfile;
    loop = atoi(argv[1]);
    GA.generation = atoi(argv[2]);
    GA.popSize = atoi(argv[3]);
    GA.chromosomeLength = atoi(argv[4]);
    GA.Pc = atof(argv[5]);
    GA.PmNumerator = atoi(argv[6]);
    GA.randomPopulationRate = atof(argv[7]);
    GA.ImmigrantRateFromBOA = atof(argv[8]);
    DE.Pn = atof(argv[9]);
    algoType = atoi(argv[10]);
    CM.numOfSamples = atoi(argv[11]);
    mkpfile=atoi(argv[12]);
    DE.noiseType=atoi(argv[13]);
    DE.problemType=atoi(argv[14]);
    DE.environmentType = atoi(argv[15]);
    DE.period=atoi(argv[16]);
    DE.severity=atof(argv[17]);

    printf("\nRunning... Problem type: %d...",DE.problemType);
    fflush(stdout);
    for(int i=1; i<=loop; i++)
    {
        myAlgorithm(i,DE.problemType,algoType,mkpfile);
    }
    cout<<"Done!"<<endl;
    return 0;
}

当我运行上述代码时,我希望输出首先打印printf()没有换行符的部分,然后打印该cout部分:

Running bla bla bla... Done!

如果我只运行一个测试用例,它可以正确运行,但是当我使用 shell 脚本并行运行多个测试用例时,它变成这样:

    Running... Problem type: 1...Running... Problem type: 1...
Running... Problem type: 1...
Running... Problem type: 1...
Running... Problem type: 1...
Running... Problem type: 1...
Running... Problem type: 1...
Running... Problem type: 1...
Running... Problem type: 2...
Running... Problem type: 2...
Running... Problem type: 2...
Running... Problem type: 2...Done!
Done!
Done!

Running... Problem type: 2...
Running... Problem type: 2...
Running... Problem type: 3...
Running... Problem type: 3...
Running... Problem type: 3...
Running... Problem type: 3...
Running... Problem type: 2...
Running... Problem type: 3...
Running... Problem type: 3...

Running... Problem type: 2...Running... Problem type: 3...
Running... Problem type: 3...Done!
Done!
Done!
Done!
Done!
Done!
Done!
Done!
Done!
Done!
Done!

有什么方法可以正确实现这一点吗?我在这里问这个问题是因为我认为这是一个与 Ubuntu 相关的问题。

答案1

见面GNUparallel 平行安装sudo apt install parallel):

GNU parallel 是一个使用一台或多台计算机并行执行作业的 shell 工具。(…)[它]确保命令的输出与您按顺序运行命令时获得的输出相同。(man parallel

对于重复参数的情况,你可以使用bash括号扩展轻松构建命令行。基本语法是parallel COMMAND {} ::: ARGUMENTS,如果您想为每次运行提供多个参数,请注意正确引用防止单词分裂,例如:

$ parallel echo ./run some args {} ::: {"1 0 "{10,25},"2 0 10"}\ {0.{1,2,5},1}
./run some args 1 0 10 0.1
./run some args 1 0 10 0.2
./run some args 1 0 10 0.5
./run some args 1 0 10 1
./run some args 1 0 25 0.1
./run some args 1 0 25 0.2
./run some args 1 0 25 0.5
./run some args 1 0 25 1
./run some args 2 0 10 0.1
./run some args 2 0 10 0.2
./run some args 2 0 10 0.5
./run some args 2 0 10 1

答案2

你的脚本输出不会混合在一起,如果你重定向输出将每个命令复制到不同的文件。例如:

./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 1 0 10 0.1 > run-0.1.log &
./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 1 0 10 0.2 > run-0.2.log &
./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 1 0 10 0.5 > run-0.5.log &
./run 50 5000 100 100 1.0 2 0.3 0.3 0.05 1 101 0 2 1 0 10 1 > run-1.0.log &

您稍后可以打开这些文件并检查每个过程的详细信息。

或者,如果您根本不想看到输出,请将其重定向到/dev/null

相关内容