GNU Parallel threads 运行 函数没有一些给定的参数

GNU Parallel threads running function without some of its given args

运行 一组跨集群中多个节点的 GNU 并行作业,并观察到所有线程似乎都在节点上休眠(包括调用命令的本地节点)。经过进一步检查,发现 GNU Parallel 在运行分配为作业 的函数时似乎正在删除一些参数。检查 parallel --version 确认这是并行的 GNU 版本(版本 20160222)。

有问题的代码看起来像

bcpexport() {
    filename=
    TO_SERVER_ODBCDSN=
    DB= 
    TABLE= 
    USER=
    PASSWORD=
    RECOMMEDED_IMPORT_MODE= 
    DELIMITER=

    <do some stuff to the given file arg  to BCP copy file contents to some MSSQL Server, function ends with...>
    
    /opt/mssql-tools/bin/bcp "$TABLE" in "$filename" \
        $TO_SERVER_ODBCDSN \
        -U $USER -P $PASSWORD \
        -d $DB \
        $RECOMMEDED_IMPORT_MODE \
        -t "\t" \
        -e "$(dirname $filename)/bcperrors/$(basename $filename).bcperror.log"
}
export -f bcpexport
parallel -q -j $parallelization_pernode --sshloginfile $basedir/src/parallel-nodes.txt --env bcpexport \
    bcpexport {} "$TO_SERVER_ODBCDSN" $DB $TABLE $USER $PASSWORD $RECOMMEDED_IMPORT_MODE $DELIMITER \
    ::: $DATAFILES/$TARGET_GLOB

它使用 Microsoft BCP (https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-migrate-bcp?view=sql-server-2017) 通过在一组节点上分发作业将 TSV 数据复制到 MSSQL Server 数据库中。


休眠过程:

查看通过 clustershell (https://clustershell.readthedocs.io/en/latest/tools/clush.html)

跨节点启动的进程时
clush -b -w mapr001,mapr005,mapr006 "ps -aux | grep bcp"

看到一堆休眠进程(注意 S,参见 https://askubuntu.com/a/360253/760862),如下所示(添加换行符以提高可读性)

me 135296 14.5 0.0 77596 6940 ? S 00:32 0:01

/opt/mssql-tools/bin/bcp TABLENAME in /path/to/tsv/1_16_0.tsv -D -S MyMSSQLServer -U myusername -P -d myDB -c -t \t -e /path/to/logfile

请注意密码 arg -P 为空。当 运行 在本地使用相同的功能 时, 不会发生这种情况。这些线程似乎永远处于休眠状态(我假设 MSSQL Server 正在等待密码,但由于空白,none 已经给出,因此没有响应)。


奇数参数:

我也看到了一些流程

me 11055 12.6 0.0 119640 1816 ? S 00:46 0:08

/bin/bash -c bcpexport() { filename=; TO_SERVER_ODBCDSN=; DB=; TABLE=; USER=; PASSWORD=; RECOMMEDED_IMPORT_MODE=; DELIMITER=; some stuff from the function; /opt/mssql-tools/bin/bcp "$TABLE" in "$filename" $TO_SERVER_ODBCDSN -U $USER -P $PASSWORD -d $DB $RECOMMEDED_IMPORT_MODE -t "\t" -e "$(dirname $filename)/bcperrors/$(basename $filename).bcperror.log" };

export -f bcpexport >/dev/null;

bcpexport /mapr/uceramapr.cluster.local//etl/ucera_internal/internal_etl/hph_clarity/version-2/stages/storage/CLARITY_TDL/tsv/1_27_0.tsv -D\ -S\ myODBCDSN myDB TABLENAME myuser mypassword -c \t

这似乎显示(对使用 GNU Parallel 非常陌生)GNU Parallel 从分配的作业中获取导出的函数并应用参数。但是,您可以看到调用并行分配的函数作为最后显示的作业具有 args -D\ -S\ myODBCDSN ,它最初位于 $TO_SERVER_ODBCDSN 变量中(这就是为什么它在引号中parallel 调用以及为什么 parallel 调用使用 -q 选项)。但是现在不是像单引号一样传递,而是 似乎 传递字符串的每一部分,就好像它被空格分开一样(尽管有 -q 选项). IDK 这对整体问题有何贡献(同样,对于 Parallel 来说非常新),但它看起来肯定不正确。

这对我来说很奇怪任何建议或调试建议将不胜感激。


UPDATE:进一步调试为什么这些线程正在休眠表明它们 可能 事实上正在做他们预期的工作(这意味着问题 可能 来自 BCP 本身(参见 )). From https://unix.stackexchange.com/a/47259/260742 and https://unix.stackexchange.com/a/36200/260742

A process in S state is usually in a blocking system call, such as reading or writing to a file or the network, or waiting for another called program to finish.

Your process will be in S state when it is doing reads and possibly writes that are blocking. Can also happen while waiting on semaphores or other synchronization primitives... This is all normal and expected, and not usually a problem... you don't want it to waste CPU while it's waiting for user input.

但是,这里强烈使用“可能”这个词,因为这并不能解释检查 ps 时线程中缺少的 $PASSWORD arg 或线程似乎从不 return 的原因。无论如何,如果根本原因与我最初的怀疑截然不同,我会更新标题和问题,以尝试对可能遇到同样问题的其他人更有帮助。

1.休眠过程:我在另一个post(参见https://whosebug.com/a/52787273/8236733)中回答了这个问题的一个非常相似的变体。基本上,太多线程在这么多节点上成倍增加,似乎使 bcp 操作正在写入的 MSSQL Server 端点数据库过载(我认为这会导致远程数据库出现某种超时问题)。

关于 ps 信息中丢失的密码 (-P) arg 值(此处再次显示)

me 135296 14.5 0.0 77596 6940 ? S 00:32 0:01

/opt/mssql-tools/bin/bcp TABLENAME in /path/to/tsv/1_16_0.tsv -D -S MyMSSQLServer -U myusername -P -d myDB -c -t \t -e /path/to/logfile

我怀疑 bcp 做了一些事情来隐藏 ps 的信息(所以它在输出中看起来只是空白(如果它看起来像 [=44= 会更容易理解) ] 相反,但无论如何......))。关于其他(对于这个理论来说很方便,还有 Microsoft-made)做这种事情的程序的讨论可以在这里找到:https://unix.stackexchange.com/q/88665/260742

2。奇怪的参数:在bash中,\字符基本上说"use the literal value next character",来自另一个SE post(https://unix.stackexchange.com/a/146665/260742

shall preserve the literal value of the following character, with the exception of a . ... The ... shall be removed

因此,即使在给定的输出中看起来单个引用变量被拆分,它实际上是作为单个参数输入的(此处的 \s 指示函数采用文字空白值,而不是将此处分隔的字符串作为不同的参数)。例如

[me@mserver001 tmp]$ ls "-l -h"
ls: invalid option -- ' '
Try 'ls --help' for more information.
[me@server001 tmp]$ ls -l\ -h
ls: invalid option -- ' '
Try 'ls --help' for more information. 
[me@server001 tmp]$ ls "-lh"
total 0
-rw-r--r-- 1 me 10001 0 Oct 12 12:22 test0.txt
-rw-r--r-- 1 me 10001 0 Oct 12 12:22 test1.txt
-rw-r--r-- 1 me 10001 0 Oct 12 12:22 test2.txt
-rw-r--r-- 1 me 10001 0 Oct 12 12:22 test3.txt
-rw-r--r-- 1 me 10001 0 Oct 12 12:22 test4.txt
-rw-r--r-- 1 me 10001 0 Oct 12 12:22 test5.txt

请注意,在前两种情况下,ls 正在读取整个参数,并且在识别引用示例和 \<blankspace> 分隔示例中的空格 ' ' 时遇到问题.

也许我应该更改 post 的标题,以便更好地匹配此问题的最终结果。