不明な理由でシェルスクリプトは早く終了します。

不明な理由でシェルスクリプトは早く終了します。

バックアップには次のスクリプトを使用しています。ボグバックアップ。しかし、奇妙な問題が発生しました。

スクリプトの次の部分は実行されません。スクリプトは次のようになり、出力は次のようになります。

スクリプト:

#!/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.*)?$'

したがって、最後の2行は実行されません。ただし、前の行をコメントアウトすると、これらの2行が実行されます。何が間違っているのか知っている人はいますか?

アップデート: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

以下はいくつかの関連質問です。

grepはtrue / falseを返すことができますか?それとも別の方法がありますか?

そして

入力が一致しないときにgrepがエラーを返さないようにする

後者の質問は同じではなくても同様の状況のようです。

答え1

つまりset -e、grep が 0 以外の値を返す場合 (つまり、パターンが一致しない) と組み合わせるとpipefailパイプラインが失敗してスクリプトが中断されるという意味です。

だからどちらにしても

  • 削除するset -e
  • 削除するpipefail
  • || truegrep常にゼロが返されるようにセグメントに1を追加します。

答え2

grep特定のパターンが見つかったかどうかに応じて終了状態を設定するように設計されており、場合によってはただこの目的のために、全ての出力が抑制される。 (これ-qがに切り替えることですgrep。)

sedテキストストリームをフィルタリングして通過するときに何らかの方法(通常は1行)に変換するように設計された「ストリームエディタ」。

これら2つのユーティリティの間には重複する部分がたくさんありますが、どちらも特定の目的に使用されます。この場合、パターンが見つかったかどうかには興味がなく、テキストストリームを渡す前にフィルタリングするだけです。これは正しいユースケースですが、sedそうではありませんgrep


sed -E '/^Remote:\s*(Checking segments.*)?$/d' delme.txt

これは、以下とまったく同じです。

grep -Ev '^Remote:\s*(Checking segments.*)?$' delme.txt

...とは別にgrepパターンに一致する行以外に他の行がない場合、コマンドはエラー終了状態を提供しますsed

関連情報