快速而简单。这个命令有效
locate -i mymovieormysong|parallel mplayer
歌曲(或电影)播放,但我无法用键盘控制 mplayer。如何做到这一点(如果可能的话)?
实际上,当我使用键盘前进或后退时,我得到了这个
^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[D^[[D^[[D
Edit1:使用 -u (取消分组)选项,输出出现,但当我按下键盘控制 mplayer 时仍然出现 [C 和 [D
快速而简单。这个命令有效
locate -i mymovieormysong|parallel mplayer
歌曲(或电影)播放,但我无法用键盘控制 mplayer。如何做到这一点(如果可能的话)?
实际上,当我使用键盘前进或后退时,我得到了这个
^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[D^[[D^[[D
Edit1:使用 -u (取消分组)选项,输出出现,但当我按下键盘控制 mplayer 时仍然出现 [C 和 [D
考虑GNU 并行手册示例中的数据--group-by
:
cat > table.csv <<"EOF"
UserID, Consumption
123, 1
123, 2
12-3, 1
221, 3
221, 1
2/21, 5
EOF
有没有一种方法可以按一列对记录进行分组,并将组中另一列的所有值作为命令行参数写入?
该命令不会分组,但会提供我想要的输出结构。
cat table.csv | parallel --colsep , --header : -kN1 echo UserID {1} Consumption {2}
UserID 123 Consumption 1
UserID 123 Consumption 2
UserID 12-3 Consumption 1
UserID 221 Consumption 3
UserID 221 Consumption 1
UserID 2/21 Consumption 5
什么命令会给我这样的输出?
UserID 123 Consumption 1 2
UserID 12-3 Consumption 1
UserID 221 Consumption 3 1
UserID 2/21 Consumption 5
我还想限制“消耗”值的数量。
假设其中一组有超过 4 个人。
cat > table.csv <<"EOF"
UserID, Consumption
123, 1
123, 2
123, 3
123, 4
123, 5
123, 6
123, 7
12-3, 1
221, 3
221, 1
2/21, 5
EOF
我希望命令行包含不超过 4 个“消耗”值。
UserID 123 Consumption 1 2 3 4
UserID 123 Consumption 5 6 7
UserID 12-3 Consumption 1
UserID 221 Consumption 3 1
UserID 2/21 Consumption 5
该手册展示了如何使用--group-by
来选择正确的组。
cat table.csv | \
parallel --pipe --colsep , --header : --group-by UserID -kN1 wc
4 行wc
输出意味着它对 4 组进行操作。例如,第一组有 3 行、6 个单词和 40 个字符。
3 6 40
2 4 30
3 6 40
2 4 30
为了使组输入更清晰,我交换wc
为cat
.
cat table.csv | \
parallel --pipe --colsep , --header : --group-by UserID -kN1 cat
cat 输出显示并行将原始输入行传递给作业并将标题行复制为每个组的第一行。
UserID, Consumption
123, 1
123, 2
UserID, Consumption
12-3, 1
UserID, Consumption
221, 3
221, 1
UserID, Consumption
2/21, 5
问题是--group-by
使 Parallel 使用标准输入而不是命令行参数。我看不出有什么办法可以解决这个问题。
我是否需要更改将参数传递给 GNU Parallel 的方式?在使用 GNU 并行执行之前,我是否需要使用其他工具来创建正确的格式?
我正在使用 GNU 并行版本 20231122。
我尝试使用 GNU Parallel 为每个输入参数运行命令,使用该参数作为命令的工作目录(不将其附加到命令行)。
基本上,我需要做的是:
/foo -> "cd /foo; mycmd"
/bar -> "cd /bar; mycmd"
/baz -> "cd /baz; mycmd"
Parallel has--workdir
似乎可以通过支持{}
替换字符串来实现我想要的功能:
--workdir mydir
--wd mydir作业将在目录 mydir 中运行。默认值是本地计算机的当前目录,以及远程计算机的登录目录。
<...>
mydir 可以包含 GNU Parallel 的替换字符串。
为了防止参数被附加到命令行,我尝试使用-n0
or -N0
:
--max-args 最大参数
-n 最大参数每个命令行最多使用 max-args 个参数。
<...>
-n 0 表示读取一个参数,但在命令行上插入 0 个参数。
然而,这似乎不起作用:
$ mkdir -p $HOME/{foo,bar,baz}
$ printf '%s\n' $HOME/{foo,bar,baz} | parallel --workdir '{}' -n0 'pwd'
parallel: Error: Cannot change into non-executable dir : No such file or directory
请注意 之前的空格:
,这不是 GNU 并行中的拼写错误,而是表明 workdir 被评估为空字符串。如果我在 前面添加一个固定字符串{}
,这一点就会变得很明显,在这种情况下,所有 pwd 都会打印该固定字符串:
$ printf '%s\n' $HOME/{foo,bar,baz} | parallel --workdir '/{}' -N0 'pwd'
/
/
/
我究竟做错了什么?
我有一个像这样的过程,它会以随机间隔生成预定义数量的文件:
#!/bin/bash
for i in {1..10}
do
sleep $(shuf -i 20-60 -n 1)
echo $i > file_$i.txt
done
我有另一个进程,使用 GNU Parallel 独立运行在每个文件上,如下所示:
parallel wc -l ::: file_{1..10}.txt
正如预期的那样,并行在当前可用的文件上运行。有没有办法让并行等待剩余文件可用并尽快运行?
当我使用 时,我无法追加到数组parallel
,使用 for 循环没有问题。
append() { arr+=("$1"); }
export -f append
parallel -j 0 append ::: {1..4}
declare -p arr
-bash: declare: arr: not found
for i in {1..4}; do arr+=("$i"); done
declare -p arr
declare -a arr=([0]="1" [1]="2" [2]="3" [3]="4")
我认为第一个示例是函数式风格的 for 循环的翻译,那么这是怎么回事呢?
我正在尝试并行并行运行,似乎我遇到了一种理想的解决方案。
我想连续运行一组作业——称它们为 A-1、A-2、A-3 等等。这些将与 --jobs 1(或 sem?)一起运行。
我想并行运行这些集合——称它们为 A、B、C 等等。这些将以默认数量的作业(核心)运行。
“A”组作业中的作业数量可能与“B”组作业中的作业数量不同;C或其他类似。
从视觉上看,横轴是时间,纵轴是作业集:
A-1--->A-2--->A-3--->
B-1->B-2-->B-3-->B-4--->
C-1-------------C-2--->
D-1------------------>
为此,我们假设所有作业都处于睡眠状态 $((RANDOM % 10))。
我假设工作集和工作之间必须有某种联系(ala --link)——A 有 1、2 和 3;B 有 1、2、3 和 4;C 有 1 和 2;和 D 只有 1,使用上面的视觉效果。
这可能是我尝试做的更好的例子,使用@ole-tang 的解决方案
$ declare -fp apples bananas cherries dates
apples ()
{
echo -n grannysmith fiji pinklady | parallel -d' ' -j1 'echo apples-{#}: {};sleep $((RANDOM % 3))'
}
declare -fx apples
bananas ()
{
echo -n plantain cavadish red manzano | parallel -d' ' -j1 'echo bananas-{#}: {};sleep $((RANDOM % 3))'
}
declare -fx bananas
cherries ()
{
echo -n sweet sour red yellow bing | parallel -d' ' -j1 'echo cherries-{#}: {};sleep $((RANDOM % 3))'
}
declare -fx cherries
dates ()
{
echo -n medjool khola | parallel -d' ' -j1 'echo dates-{#}: {};sleep $((RANDOM % 3))'
}
declare -fx dates
$ parallel ::: apples bananas cherries dates
bananas-1: plantain
bananas-2: cavadish
bananas-3: red
bananas-4: manzano
dates-1: medjool
dates-2: khola
apples-1: grannysmith
apples-2: fiji
apples-3: pinklady
cherries-1: sweet
cherries-2: sour
cherries-3: red
cherries-4: yellow
cherries-5: bing
当我尝试编写这样的管道时:
git branch | rg '^\*' | parallel git pull {}
我遇到了空格问题。因为分支名称有前导空格,所以并行最终会尝试运行git pull ' foo'
这是错误的。
GNU Parallel 是否有一个说法是“去除尾随/前导空格”?或者,是否有一个单独的程序可以做到这一点?
我知道我可以:
cut -c 3-
,但这仅在前导空格一致的情况下才有效sed
or awk
,但这些导致每次都必须输入复杂的表达式我正在编译一个庞大的命令列表(所有命令都执行相同的操作),但由于编译该列表需要很长时间,我希望在完成之前开始执行(每个命令的执行通常需要比创建另一个更长的时间,所以没有真正的列表枯竭的风险)。
执行命令列表的正常方法是编写一个列出命令的 shell 脚本,但是当我开始执行脚本时,我不能再添加它了。
到目前为止我发现的方法是将命令放入command.list
并拥有parallel --jobs 1 --line-buffer :::: command.list
,但由于它涉及使用parallel
(我正在使用 GNU 并行,我不知道它是否可以与 more-utils 中的程序一起使用)用于非并行执行事物,我认为这有点滥用parallel
.
有没有更简单的方法呢?如果我搞砸了某些事情并且列表确实用完了,那么可以跟踪哪些命令已被执行,这会很好。
我有一个bash
脚本可以通过ssh
. 它在并行版本中使用 GNU parallel
,在顺序版本中使用 for 循环。
脚本是这样使用的:
foreach_server "cd $dir && find -name '*.png' | wc -l"
foreach_server "cd $dir && git --no-pager status"
有时我需要访问conda
环境中的可执行文件(https://docs.conda.io/en/latest/),而我发现使这项工作正常进行的唯一方法是使用交互式 shell,即bash -ic
在命令之前使用我想像这样执行,以便ssh $host bash -ic $cmd
加载 conda 环境。不幸的是,这会导致两个错误消息stderr
,我无法阻止:
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
所以我做了一个过滤器,用sed
它删除这两行stderr
并传递给其他行stderr
:
ssh $host "$@" 2> >(sed -e "$filter1" -e "$filter2" >&2)
过滤器在顺序版本中sed
工作正常,但并行版本在脚本末尾挂起,表明 sed 进程处于活动状态但没有工作。我怎样才能防止这种情况?
我怀疑问题出在进程替换上,但我真的无法诊断出问题所在。
#!/bin/bash
set -u
exit_trap() {
echo "Interrupted"
exit 1
}
trap exit_trap SIGINT
filter1='/^bash: cannot set terminal process group/d'
filter2='/^bash: no job control in this shell/d'
hosts=("host1" "host2") # more hosts in the real file
if [ -z ${serial+x} ];
then
# Parallel version ==> THIS VERSION HANGS AT THE END, AFTER ALL OUTPUT HAS BEEN WRITTEN
echo ${hosts[@]} | sed 's/ /\n/g' | parallel "echo ----- {} ----- && ssh {} \"$@\"" 2> >(sed -e "$filter1" -e "$filter2" >&2)
else
# Serial version ==> THIS VERSION WORKS FINE
for host in ${hosts[@]};
do
echo "------------------ $host ------------------"
ssh $host "$@" 2> >(sed -e "$filter1" -e "$filter2" >&2)
echo "--------------------------------------$(echo $host | sed 's/./-/g')"
done
fi
我想在两台电脑上使用 ffmpeg,我知道并行可以做到我使用这个 cli
parallel --trc {.}.mkv -S virtual,: 'ffmpeg -y -i {} -vf yadif,crop=720:550:0:12,scale=640:352 -c:v libx264 -c:a aac -b:v 1500k -b:a 128k -metadata language=eng -metadata title="example" -aspect 16:9 {.}.mkv' ::: example.mpg
它在虚拟(OK)上传输文件 example.mpg,然后仅在远程 pc(虚拟)上运行该命令!但是这条线-S virtual,
:即使在本地电脑上也不要要求并行运行?我的目的是使用 gnu 并行在两台或多台 pc 上分配负载/cpu 使用,例如 localpc 上 50% 的负载,远程上 50% 的负载,可能吗?或者我需要更复杂的东西,比如旧的好 openmosix 集群?