다음과 같은 스크립트가 있습니다.
#!/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