我有一个像这样的脚本:
#!/bin/bash
if findmnt --source UUID=309689b5-ea5c-4175-84c7-192631553eab --source PARTLABEL=WDPurple8TB --mountpoint /media/ismail/WDPurple8TB --types ext4 --noheadings; then
udisksctl unmount -b /dev/disk/by-label/WDPurple8TB
udisksctl power-off -b /dev/disk/by-label/WDPurple8TB
echo "Power-Off /dev/disk/by-label/WDPurple8TB"
fi
if findmnt --source UUID=151cf7f0-461a-416f-8e44-63d799418958 --source PARTLABEL=WDPurple6TB --mountpoint /media/ismail/WDPurple6TB --types ext4 --noheadings; then
udisksctl unmount -b /dev/disk/by-label/WDPurple6TB
udisksctl power-off -b /dev/disk/by-label/WDPurple6TB
echo "Power-Off /dev/disk/by-label/WDPurple6TB"
fi
在这里,如果两个 if-fi 代码块并行运行会更好。但是,if-fi 代码块中的 stdout 和 stderr 应该成组(我的意思是它们的输出不应重叠)。我的意思是:
以下三行的 stdout 和 stderr 应在我们到达末尾后显示第一的if-fi 代码块。
udisksctl unmount -b /dev/disk/by-label/WDPurple8TB
udisksctl power-off -b /dev/disk/by-label/WDPurple8TB
echo "Power-Off /dev/disk/by-label/WDPurple8TB"
以下三行的 stdout 和 stderr 应在我们到达末尾后显示第二if-fi 代码块。
udisksctl unmount -b /dev/disk/by-label/WDPurple6TB
udisksctl power-off -b /dev/disk/by-label/WDPurple6TB
echo "Power-Off /dev/disk/by-label/WDPurple6TB"
我怎样才能做到这一点?
答案1
要序列化这些输出(和错误),您必须暂时保存至少其中一个:
#! /bin/zsh -
ret=0
umask 077 # for temp files that we recreate
if findmnt --source UUID=309689b5-ea5c-4175-84c7-192631553eab --source PARTLABEL=WDPurple8TB --mountpoint /media/ismail/WDPurple8TB --types ext4 --noheadings; then
udisksctl unmount -b /dev/disk/by-label/WDPurple8TB &&
udisksctl power-off -b /dev/disk/by-label/WDPurple8TB &&
echo "Power-Off /dev/disk/by-label/WDPurple8TB"
fi & pid=$!
out==() err==()
if findmnt --source UUID=151cf7f0-461a-416f-8e44-63d799418958 --source PARTLABEL=WDPurple6TB --mountpoint /media/ismail/WDPurple6TB --types ext4 --noheadings; then
udisksctl unmount -b /dev/disk/by-label/WDPurple6TB &&
udisksctl power-off -b /dev/disk/by-label/WDPurple6TB &&
echo "Power-Off /dev/disk/by-label/WDPurple6TB"
fi > $out 2> $err || ret=$?
wait $pid || ret=$?
# dump the second job's errors on stderr
cat<$err >&2
# and its output to stdout:
cat<$out
# clean up the temp files
rm -f -- $out $err
# report failure if any of any of those two jobs
exit $ret
这里使用进程替换zsh
的=(...)
形式来创建临时文件。通过 sh 或 bash,您可以使用mktemp
系统上可用的任何命令来安全地创建临时文件。
严格来说,=(cmd)
并不是这样使用的,因为一旦扩展的命令完成,zsh 就会删除临时文件。在这里,我们稍后使用相同的路径重新创建它,因此它并不严格安全,因为有一个小窗口,在此期间文件可能被恶意行为者重新创建为符号链接。
对于任意数量的并行卸载,我们可以稍微分解一些事情。我们还可以打开 fds 到那些要删除的临时文件,以便从一开始就删除它们,解决上述问题并进行清理:
#! /bin/zsh -
zmodload zsh/system || exit
out=() err_read=() err_write=() out_read=() out_write=() pid=()
n=1 ret=0
stop_disk() {
local uuid=$1 label=$2
if
findmnt --source UUID=$uuid \
--source PARTLABEL=$label \
--mountpoint /media/ismail/$label \
--types ext4 \
--noheadings
then
udisksctl unmount -b /dev/disk/by-label/$label &&
udisksctl power-off -b /dev/disk/by-label/$label &&
print -r "Power-Off /dev/disk/by-label/$label"
fi
}
for uuid label (
309689b5-ea5c-4175-84c7-192631553eab WDPurple8TB
151cf7f0-461a-416f-8e44-63d799418958 WDPurple6TB
) {
() {
sysopen -wo cloexec -u out -- $1 &&
sysopen -ro cloexec -u in -- $1 &&
err_write[n]=$out err_read[n]=$in &&
sysopen -wo cloexec -u out -- $2 &&
sysopen -ro cloexec -u in -- $2 &&
out_write[n]=$out out_read[n]=$in
} =() =() || exit
stop_disk $uuid $label >&$out_write[n] 2>&$err_write[n] &
pid[n++]=$!
}
for (( i = 1; i <= n; i++ )) {
wait $pid[i] || ret=$?
cat <&$err_read[i] >&2
cat <&$out_read[i]
}
exit $ret
(未经测试)
答案2
这行得通吗:
#!/bin/bash
a() {
if findmnt --source UUID=309689b5-ea5c-4175-84c7-192631553eab --source PARTLABEL=WDPurple8TB --mountpoint /media/ismail/WDPurple8TB --types ext4 --noheadings; then
udisksctl unmount -b /dev/disk/by-label/WDPurple8TB
udisksctl power-off -b /dev/disk/by-label/WDPurple8TB
echo "Power-Off /dev/disk/by-label/WDPurple8TB"
fi
}
b() {
if findmnt --source UUID=151cf7f0-461a-416f-8e44-63d799418958 --source PARTLABEL=WDPurple6TB --mountpoint /media/ismail/WDPurple6TB --types ext4 --noheadings; then
udisksctl unmount -b /dev/disk/by-label/WDPurple6TB
udisksctl power-off -b /dev/disk/by-label/WDPurple6TB
echo "Power-Off /dev/disk/by-label/WDPurple6TB"
fi
}
export -f a b
parallel --lb ::: a b
或者:
umnt() {
uuid="$1"
label="$2"
if findmnt --source UUID="$uuid" --source PARTLABEL="$label" --mountpoint /media/ismail/"$label" --types ext4 --noheadings; then
udisksctl unmount -b /dev/disk/by-label/"$label"
udisksctl power-off -b /dev/disk/by-label/"$label"
echo "Power-Off /dev/disk/by-label/$label"
fi
}
export -f umnt
parallel --lb umnt ::: 309689b5-ea5c-4175-84c7-192631553eab 151cf7f0-461a-416f-8e44-63d799418958 :::+ WDPurple8TB WDPurple6TB