自动启动多个并行屏幕线程?

自动启动多个并行屏幕线程?

我们学校的 HPC 没有调度程序。所以没有什么比作业队列更好的了。因此,我无法通过qsub或自动化并行作业提交sbatch

我一直用来“提交”作业的方法是使用 screen: type screen,然后按Enter,然后键入./runMyJob.sh,然后按CTRL+ ,a然后按d分离。

现在我希望自动化/脚本化启动多个并行屏幕会话的过程,然后在每个会话中运行一个作业,最后分离所有屏幕会话。

正如您所看到的,在手动操作期间,我按下了EnterCTRL+ a,然后按下了d。如何编写这些按键操作的脚本?

PS:非常欢迎任何有助于在没有调度程序的 HPC 中实现并行作业提交的建议!

答案1

不要将其视为按键,而是将其视为完成任务。按键是一种交互方式。自动完成任务的方法是编写脚本。

要在屏幕中启动作业并立即将其分离,请运行

screen -md ./runMyJob.sh

如果您想让您的工作更容易找到,您可以通过-S设置会话名称的选项。

例如,您可以编写以下脚本,该脚本使用作业可执行文件的名称作为会话名称:

#!/bin/sh
screen -md -S "${1##*/}" "$@"

将其命名为类似submit,将其放在 PATH 上的目录中(单用户二进制安装位置?如何添加 Unix 哪个命令发现的主目录路径?可能有帮助),使其可执行(chmod +x ~/bin/submit)。要开始工作,请运行

submit ./runMyJob.sh

对于并行执行,您可能需要调查GNU并行

请注意,作业提交框架的作用不仅仅是启动作业。它还安排它们在有可用 CPU 时间和内存的地方运行,并将日志发送给提交者。您应该要求您的管理员建立适当的作业提交框架。

答案2

Enter, Ctrl-ad生成正常的 ASCII 代码。

pipe()因此,一个可能的解决方案可能是创建一个未命名管道( )的程序,然后fork()创建一个子进程,该子进程首先将管道的读取端绑定到其标准输入,然后screen在子进程(execve()或类似进程)中执行。如果该程序已启动,您可以将启动进程所需的命令行写入所创建管道的写入端。

如何将任务放入该程序中是另一个主题。例如,您可以自己编写一个小型调度程序(类似于作业队列和一些并行启动最多 N 个进程的代码)。

==编辑==

对于 Linux(或者也可能是一些 UN*X),程序可能如下所示:

#include <sys/types.h>
#include <sys/linux.h>
#include <unistd.h>

int main(void) {
    int fds[2] = {0};
    pid_t pid = 0;

    pipe(fds);               /* Creates an unnamed pipe */
    pid = fork();            /* Forks a new process */
    if (pid == 0) {
        static char const *argv[] = {"/usr/bin/screen", NULL};
                             /* Note: The array might need to be changed,
                              *       depending on your requirements
                              *       (eg. command-line arguments)
                              */
        dup2(fds[0], stdin); /* Binds the read end of the pipe to stdin */
        execve(argv[0], argv, NULL);
        /* If you reach this point, your execve() failed */
    }
    sleep(1);                /* Waits for the child process to execute
                              * screen */
    char const data[] = "./MyJob.sh\n\x00d";
                             /* Note: You must replace the '\x00' by the
                              *       ASCII code of C-a!
                              */
    write(fds[1], data, sizeof(data));
                             /* Writes the name of the job along with the
                              * control codes to the child process
                              */
    int retcode = 0;
    waitpid(pid, &retcode, 0);
                             /* Waits for the child process to terminate */
                             /* Note: WEXITSTATUS(retcode) gets the exit
                              *       status of the child process */
    return 0;
}

这个程序应该说明这个想法,它缺乏必要的错误处理。

相关内容