GNU Parallel -q 选项导致 BCP "unknown option" 错误(本地主机和远程主机上的字符串引号不同)
GNU Parallel -q option causing BCP "unknown option" errors (different string quotes on local vs remote hosts)
在使用 gnu parallel
使用 mssql-tools
中的 bcp
分发导出作业时看到非常奇怪的行为。 当对 parallel
使用 -q
选项时,字符串在本地主机上的解释与在远程主机上的解释不同。
运行 仅作为本地主机上文件的循环,bcp 进程不会抛出任何错误
但是,使用 parallel
分发文件导出时,bcp 进程在本地主机 上执行 抛出
/opt/mssql-tools/bin/bcp: unknown option
错误,而在 远程主机 上执行的错误(通过 --sshloginfile
参数)成功完成。 运行 的基本代码看起来像...
# setting some vars to pass
TO_SERVER_ODBCDSN="-D -S MyMSSQLServer"
TO_SERVER_IP="-S 172.18.54.22"
DB="$dest_db" #TODO: enforce being more careful with this value
TABLE="$tablename" # MUST exist beforehand, case matters
USER=$(tail -n+1 $source_home/mssql-creds.txt | head -1)
PASSWORD=$(tail -n+2 $source_home/mssql-creds.txt | head -1)
DATAFILES="/some/path/to/files/"
TARGET_GLOB="*.tsv"
RECOMMEDED_IMPORT_MODE='-c' # makes a HUGE difference, see
DELIMITER="\\t" # (currently not used) DO NOT use format like "'\t'", nested quotes seem to cause hard-to-catch error, want "\t" literal
....
bcpexport() {
filename=
TO_SERVER_ODBCDSN=
DB=
TABLE= # MUST exist beforehand, case matters
USER=
PASSWORD=
RECOMMEDED_IMPORT_MODE= # makes a HUGE difference, see
DELIMITER= # not currently used
WORKDIR=
LOGDIR=
....
/opt/mssql-tools/bin/bcp "$TABLE" in "$localfile" \
$TO_SERVER_ODBCDSN \
-U $USER -P $PASSWORD \
-d $DB \
$RECOMMEDED_IMPORT_MODE
-t "\t" \
-e ${localfile}.bcperror.log
}
export -f bcpexport
parallelization_pernode=5
parallel -q -j $parallelization_pernode \
--sshloginfile $source_home/parallel-nodes.txt \
--env bcpexport \
bcpexport {} "$TO_SERVER_ODBCDSN" $DB $TABLE $USER $PASSWORD $RECOMMEDED_IMPORT_MODE $DELIMITER $workingdir $logdir \
::: $DATAFILES/$TARGET_GLOB #from hdfs nfs gateway
查看进程的 bash 解释(通过 运行ning ps -aux | grep bcp
在主机上 parallel
在 --sshloginfile
中给出)对于我们看到的远程主机...
/bin/bash -c bcpexport() { ... /opt/mssql-tools/bin/bcp "$TABLE" in "$localfile" $TO_SERVER_ODBCDSN -U $USER -P $PASSWORD -d $DB $RECOMMEDED_IMPORT_MODE; -t "\t" -e ${localfile}.bcperror.log; ...
对于本地主机,bash 解释是...
/bin/bash -c bcpexport() { ... /opt/mssql-tools/bin/bcp "$TABLE" in "$localfile" $TO_SERVER_ODBCDSN -U $USER -P $PASSWORD -d $DB $RECOMMEDED_IMPORT_MODE; -t "\t" -e ${localfile}.bcperror.log; ...
也就是说,它们看起来一样。
我目前的想法是 bcp 命令中的“\t”被以有问题的方式解释。在不使用 -q
选项的情况下调试 parallel
我们看到...
$ parallel -j 5 --sshloginfile ./parallel-nodes.txt echo "Number {}: Running on \`hostname\`: \t" ::: 1 2 3 4 5
Number 4: Running on HW04.ucera.local: t
Number 1: Running on HW04.ucera.local: t
Number 2: Running on HW03.ucera.local: t
Number 5: Running on HW03.ucera.local: t
Number 3: Running on HW02.ucera.local: t
$ parallel -q -j 5 --sshloginfile ./parallel-nodes.txt echo "Number {}: Running on \`hostname\`: \t" ::: 1 2 3 4 5
Number 1: Running on `hostname`:
Number 4: Running on `hostname`:
Number 3: Running on `hostname`: \t
Number 2: Running on `hostname`: \t
Number 5: Running on `hostname`: \t
bcp 命令需要 "\t" 文字而不是 "t" 文字(我怀疑其他几个类似的字符串损坏(而且我确实相信 \t 是 bcp 的默认值,但这是只是一个例子,想保留 \t 以便代码清晰)),但不确定如何为 本地和远程节点获得此 ,甚至不知道为什么这种行为因远程与本地而异。
基本上,需要本地和远程主机的字符串完全相同,即使字符串中有空格或转义字符(注意,我认为这曾经是并非如此(在其他机器上有较旧的脚本没有这个问题))
不确定这是 parallel
问题还是 bcp
问题(目前认为 parallel
中的 -q
选项出了问题,但不确定)。任何人有任何调试建议或修复?关于可能发生的事情的想法?
首先,hostname
没有展开的原因是-q
。它引用 ` 使其不会扩展。
其次,我认为您看到的是内置 echo
和 /bin/echo
中的不同行为。内置 echo
取决于 shell。这里我比较echo \\t
在不同的shells:
$ parallel --onall --tag -S sh@lo,bash@lo,csh@lo,tcsh@lo,ksh@lo,zsh@lo echo \\t ::: a
bash@lo \t a
tcsh@lo a
sh@lo a
ksh@lo \t a
zsh@lo a
csh@lo \t a
但是,这并不能使您更接近解决方案。如果我是你,我会使用 env_parallel
来复制环境变量。如果远程系统上的登录 shell 与您的 shell 不同,则设置 PARALLEL_SHELL
以强制使用 shell.
所以:
#!/bin/bash
env_parallel --session
# setting some vars to pass
TO_SERVER_ODBCDSN="-D -S MyMSSQLServer"
:
:
PARALLEL_SHELL=bash env_parallel -q -j $parallelization_pernode ...
(no need to use neither --env nor 'export -f' when using 'env_parallel --session')
# Cleanup (not needed if this is the last line in the script)
env_parallel --end-session
在使用 gnu parallel
使用 mssql-tools
中的 bcp
分发导出作业时看到非常奇怪的行为。 当对 parallel
使用 -q
选项时,字符串在本地主机上的解释与在远程主机上的解释不同。
运行 仅作为本地主机上文件的循环,bcp 进程不会抛出任何错误
但是,使用 parallel
分发文件导出时,bcp 进程在本地主机 上执行 抛出
/opt/mssql-tools/bin/bcp: unknown option
错误,而在 远程主机 上执行的错误(通过 --sshloginfile
参数)成功完成。 运行 的基本代码看起来像...
# setting some vars to pass
TO_SERVER_ODBCDSN="-D -S MyMSSQLServer"
TO_SERVER_IP="-S 172.18.54.22"
DB="$dest_db" #TODO: enforce being more careful with this value
TABLE="$tablename" # MUST exist beforehand, case matters
USER=$(tail -n+1 $source_home/mssql-creds.txt | head -1)
PASSWORD=$(tail -n+2 $source_home/mssql-creds.txt | head -1)
DATAFILES="/some/path/to/files/"
TARGET_GLOB="*.tsv"
RECOMMEDED_IMPORT_MODE='-c' # makes a HUGE difference, see
DELIMITER="\\t" # (currently not used) DO NOT use format like "'\t'", nested quotes seem to cause hard-to-catch error, want "\t" literal
....
bcpexport() {
filename=
TO_SERVER_ODBCDSN=
DB=
TABLE= # MUST exist beforehand, case matters
USER=
PASSWORD=
RECOMMEDED_IMPORT_MODE= # makes a HUGE difference, see
DELIMITER= # not currently used
WORKDIR=
LOGDIR=
....
/opt/mssql-tools/bin/bcp "$TABLE" in "$localfile" \
$TO_SERVER_ODBCDSN \
-U $USER -P $PASSWORD \
-d $DB \
$RECOMMEDED_IMPORT_MODE
-t "\t" \
-e ${localfile}.bcperror.log
}
export -f bcpexport
parallelization_pernode=5
parallel -q -j $parallelization_pernode \
--sshloginfile $source_home/parallel-nodes.txt \
--env bcpexport \
bcpexport {} "$TO_SERVER_ODBCDSN" $DB $TABLE $USER $PASSWORD $RECOMMEDED_IMPORT_MODE $DELIMITER $workingdir $logdir \
::: $DATAFILES/$TARGET_GLOB #from hdfs nfs gateway
查看进程的 bash 解释(通过 运行ning ps -aux | grep bcp
在主机上 parallel
在 --sshloginfile
中给出)对于我们看到的远程主机...
/bin/bash -c bcpexport() { ... /opt/mssql-tools/bin/bcp "$TABLE" in "$localfile" $TO_SERVER_ODBCDSN -U $USER -P $PASSWORD -d $DB $RECOMMEDED_IMPORT_MODE; -t "\t" -e ${localfile}.bcperror.log; ...
对于本地主机,bash 解释是...
/bin/bash -c bcpexport() { ... /opt/mssql-tools/bin/bcp "$TABLE" in "$localfile" $TO_SERVER_ODBCDSN -U $USER -P $PASSWORD -d $DB $RECOMMEDED_IMPORT_MODE; -t "\t" -e ${localfile}.bcperror.log; ...
也就是说,它们看起来一样。
我目前的想法是 bcp 命令中的“\t”被以有问题的方式解释。在不使用 -q
选项的情况下调试 parallel
我们看到...
$ parallel -j 5 --sshloginfile ./parallel-nodes.txt echo "Number {}: Running on \`hostname\`: \t" ::: 1 2 3 4 5
Number 4: Running on HW04.ucera.local: t
Number 1: Running on HW04.ucera.local: t
Number 2: Running on HW03.ucera.local: t
Number 5: Running on HW03.ucera.local: t
Number 3: Running on HW02.ucera.local: t
$ parallel -q -j 5 --sshloginfile ./parallel-nodes.txt echo "Number {}: Running on \`hostname\`: \t" ::: 1 2 3 4 5
Number 1: Running on `hostname`:
Number 4: Running on `hostname`:
Number 3: Running on `hostname`: \t
Number 2: Running on `hostname`: \t
Number 5: Running on `hostname`: \t
bcp 命令需要 "\t" 文字而不是 "t" 文字(我怀疑其他几个类似的字符串损坏(而且我确实相信 \t 是 bcp 的默认值,但这是只是一个例子,想保留 \t 以便代码清晰)),但不确定如何为 本地和远程节点获得此 ,甚至不知道为什么这种行为因远程与本地而异。
基本上,需要本地和远程主机的字符串完全相同,即使字符串中有空格或转义字符(注意,我认为这曾经是并非如此(在其他机器上有较旧的脚本没有这个问题))
不确定这是 parallel
问题还是 bcp
问题(目前认为 parallel
中的 -q
选项出了问题,但不确定)。任何人有任何调试建议或修复?关于可能发生的事情的想法?
首先,hostname
没有展开的原因是-q
。它引用 ` 使其不会扩展。
其次,我认为您看到的是内置 echo
和 /bin/echo
中的不同行为。内置 echo
取决于 shell。这里我比较echo \\t
在不同的shells:
$ parallel --onall --tag -S sh@lo,bash@lo,csh@lo,tcsh@lo,ksh@lo,zsh@lo echo \\t ::: a
bash@lo \t a
tcsh@lo a
sh@lo a
ksh@lo \t a
zsh@lo a
csh@lo \t a
但是,这并不能使您更接近解决方案。如果我是你,我会使用 env_parallel
来复制环境变量。如果远程系统上的登录 shell 与您的 shell 不同,则设置 PARALLEL_SHELL
以强制使用 shell.
所以:
#!/bin/bash
env_parallel --session
# setting some vars to pass
TO_SERVER_ODBCDSN="-D -S MyMSSQLServer"
:
:
PARALLEL_SHELL=bash env_parallel -q -j $parallelization_pernode ...
(no need to use neither --env nor 'export -f' when using 'env_parallel --session')
# Cleanup (not needed if this is the last line in the script)
env_parallel --end-session