我正在使用以下脚本进行备份,使用博格备份。但我遇到了一个奇怪的问题
下面的脚本的一部分不执行。脚本如下,然后是输出
脚本:
#!/bin/bash
set -ex
set -o pipefail
export SERVER="myserver"
CLEVEL=zlib,9
. /home/faheem/.keychain/${HOSTNAME}-sh
#borg init -e none faheem@$SERVER:/mnt/backup-test
borg create -c 30 --compression $CLEVEL --stats faheem@ramnode:/mnt/backup-test::`hostname`-`date +%Y-%m-%d:%H.%M` /home/faheem/test-borg
{ borg check faheem@$SERVER:/mnt/backup-test 2>&1 1>&3 | tr '\r' '\n' | grep -Ev "^Remote:\s*(Checking segments.*)?$" 1>&2; } 3>&1
mapfile -t testarchives < <(borg list --short faheem@$SERVER:/mnt/backup-test)
borg extract -n "faheem@$SERVER:/mnt/backup-test"::"${testarchives[-1]}"
输出:
+ set -o pipefail
+ export SERVER=ramnode
+ SERVER=ramnode
+ CLEVEL=zlib,9
+ . /home/faheem/.keychain/orwell-sh
++ SSH_AUTH_SOCK=/tmp/ssh-F7Uzg6CeQoTY/agent.5660
++ export SSH_AUTH_SOCK
++ SSH_AGENT_PID=5661
++ export SSH_AGENT_PID
++ hostname
++ date +%Y-%m-%d:%H.%M
+ borg create -c 30 --compression zlib,9 --stats faheem@ramnode:/mnt/backup-test::orwell-2016-09-16:05.04 /home/faheem/test-borg
+ borg check faheem@ramnode:/mnt/backup-test
+ tr '\r' '\n'
+ grep -Ev '^Remote:\s*(Checking segments.*)?$'
所以最后两行不会执行。但如果我注释掉前面的行,这两行就会执行。有谁知道出了什么问题?
更新:如果我取出 grep (即替换)
{ borg check faheem@$SERVER:/mnt/backup-test 2>&1 1>&3 | tr '\r' '\n' | grep -Ev "^Remote:\s*(Checking segments.*)?$" 1>&2; } 3>&1
和
{ borg check faheem@$SERVER:/mnt/backup-test 2>&1 1>&3 | tr '\r' '\n' 1>&2; } 3>&1
我明白了
+ set -o pipefail
+ export SERVER=ramnode
+ SERVER=ramnode
+ CLEVEL=zlib,9
+ . /home/faheem/.keychain/orwell-sh
++ SSH_AUTH_SOCK=/tmp/ssh-F7Uzg6CeQoTY/agent.5660
++ export SSH_AUTH_SOCK
++ SSH_AGENT_PID=5661
++ export SSH_AGENT_PID
++ hostname
++ date +%Y-%m-%d:%H.%M
+ borg create -c 30 --compression zlib,9 --stats faheem@ramnode:/mnt/backup-test::orwell-2016-09-17:03.18 /home/faheem/test-borg
+ borg check faheem@ramnode:/mnt/backup-test
+ tr '\r' '\n'
Remote: Checking segments 0.0%
Remote:
+ mapfile -t testarchives
++ borg list --short faheem@ramnode:/mnt/backup-test
+ borg extract -n faheem@ramnode:/mnt/backup-test::orwell-2016-09-17:03.18
该Remote:
行是否对应于grep
无法匹配模式并返回非零?
以下是几个相关问题:
和
后一个问题似乎是类似的情况,即使不是相同的。
答案1
这set -e
意味着如果 grep 返回非零(即模式不匹配),那么与 结合pipefail
意味着管道失败并导致脚本中止。
所以要么
- 消除
set -e
- 消除
pipefail
|| true
在段中添加一个grep
以确保始终返回零
答案2
grep
旨在根据是否找到特定模式来设置退出状态,在某些情况下甚至使用仅有的为此目的,任何输出都会被抑制。 (这就是-q
切换到 的目的grep
。)
sed
是“流编辑器”,旨在过滤文本流,并在文本流通过时以某种方式(通常是逐行)对其进行转换。
尽管这两个实用程序之间有很多重叠,但它们都有特定的用途。在这种情况下,您显然对是否找到模式不感兴趣,您只想在传递文本流之前对其进行过滤。这是一个正确的用例sed
,而不是grep
。
sed -E '/^Remote:\s*(Checking segments.*)?$/d' delme.txt
这完全等同于:
grep -Ev '^Remote:\s*(Checking segments.*)?$' delme.txt
...除了grep
如果除了与模式匹配的行之外没有任何行,该命令将给出错误退出状态,并且sed
不会。