Bash 陷阱错误不存在';我不能用管子工作

Bash 陷阱错误不存在';我不能用管子工作,bash,Bash,我正在尝试使用trap“ERR创建一个系统备份脚本。我意识到当命令是管道的一部分时,陷阱不会被调用 以下是我的一些代码部分不适用于trap”“ERR OpenFiles=$(lsof "$Source" | wc -l) PackagesList=$(dpkg --get-selections | awk '!/deinstall|purge|hold/ {print $1}' | tee "$FilePackagesList") 如果不使用if[“$?”-eq 0],如何使其工作;然后是,还

我正在尝试使用
trap“ERR
创建一个系统备份脚本。我意识到当命令是管道的一部分时,陷阱不会被调用

以下是我的一些代码部分不适用于
trap”“ERR

OpenFiles=$(lsof "$Source" | wc -l)
PackagesList=$(dpkg --get-selections | awk '!/deinstall|purge|hold/ {print $1}' | tee "$FilePackagesList")
如果不使用
if[“$?”-eq 0],如何使其工作;然后是
,还是类似的编码?因为这就是我这样宣布陷阱的原因

这是剧本

root@Lian-Li:~# cat /usr/local/bin/create_incremental_backup_of_system.sh 
#!/bin/bash
# Create an incremental GNU-standard backup of important system-files.
# This script works with Debian Jessie and newer systems.
# Created for my lian-li NAS 2016-11-27.

MailTo="admin@example.com"  # Mail Address of an admin

Source="boot etc root usr/local usr/lib/cgi-bin var/www"
BackupDirectory=/media/hdd1/backups/lian-li

SubDir="system.d"
FileTimeStamp=$(date "+%Y%m%d%H%M%S")
FileName=$(uname -n)
File="${BackupDirectory}/${SubDir}/${FileName}-${FileTimeStamp}.tgz"
FileIncremental="${BackupDirectory}/${SubDir}/${FileName}.gtar"
FilePackagesList="${BackupDirectory}/${SubDir}/installed_packages_on_${FileName}.txt"

# have2do ...
# Backup rotate

MailContent="None"
TimeStamp=$(date "+%F %T")              # This format "2011-12-31 23:59:59" is needed to read the journal
exec 1> >(logger -i -s -t "$0" -p 3) 2>&1   # all error messages are redirected to syslog journal and after that to stdout
trap "BriefExit" ERR        # Provide information for an admin (via sendmail) when an error occurred and exit the script

function BriefExit(){
    rm -f "$File"
    if [ "$MailContent" = "None" ]
    then
        case "$LANG" in
        de_DE.UTF-8)
            echo "Beende Skript, aufgrund vorherige Fehler." 1>&2
        ;;
        *)
            echo "Stopping script because of previous error(s)." 1>&2
        ;;
        esac
        MailContent=$(journalctl -p 3 -o "short" --since="$TimeStamp" --no-pager)
        ScriptName="${0##*/}"
        SystemName=$(uname -n)
        MailSubject="${SystemName}: ${ScriptName}"
        echo -e "Subject: ${MailSubject}\n\n${MailContent}\n" | sendmail "$MailTo"
    fi
    exit 1
}

if [ ! -d "${BackupDirectory}/${SubDir}" ]
then
    mkdir -p "${BackupDirectory}/${SubDir}"
fi

LoopCount=0
OpenFiles=1
cd /
while [ "$OpenFiles" -ne 0 ]
do
    if [ "$LoopCount" -le 180 ]
    then
        sleep 1
        OpenFiles=$(lsof $Source | wc -l)
        LoopCount=$(($LoopCount + 1))
    else
        echo "Closing Script. Reason: Can't create incremental backup, because some files are open." 1>&2
        BriefExit
    fi
done

tar -cpzf "$File" -g "$FileIncremental" $Source
chmod 0700 "$File"

PackagesList=$(dpkg --get-selections | awk '!/deinstall|purge|hold/ {print $1}' | tee "$FilePackagesList")
while read -r PackageName
do
    case "$PackageName" in
    minidlna)
        # Code ...
    ;;
    slapd)
        # Code ...
    ;;
    esac
done <<< "$PackagesList"

exit 0
root@Lian-Li:~#cat/usr/local/bin/create#u incremental#u backup#u of_system.sh
#!/bin/bash
#创建重要系统文件的增量GNU标准备份。
#此脚本适用于Debian Jessie和更新的系统。
#为我的lian li NAS 2016-11-27创建。
MailTo=”admin@example.com“#管理员的邮件地址
Source=“boot etc root usr/local usr/lib/cgi bin var/www”
BackupDirectory=/media/hdd1/backups/lian li
SubDir=“system.d”
FileTimeStamp=$(日期“+%Y%m%d%H%m%S”)
文件名=$(uname-n)
File=“${BackupDirectory}/${SubDir}/${FileName}-${FileTimeStamp}.tgz”
FileIncremental=“${BackupDirectory}/${SubDir}/${FileName}.gtar”
FilePackageList=“${BackupDirectory}/${SubDir}/installed_packages_on_${FileName}.txt”
#有两个。。。
#后备轮换
MailContent=“无”
时间戳=$(日期“+%F%T”)#阅读日志需要此格式“2011-12-31 23:59:59”
exec 1>>(logger-i-s-t“$0”-p3)2>&1#所有错误消息都会重定向到syslog日志,然后再重定向到stdout
陷阱“简短退出”错误#在发生错误时为管理员提供信息(通过sendmail)并退出脚本
函数退出(){
rm-f“$File”
如果[“$MailContent”=“无”]
然后
中的“$LANG”案例
德乌德(UTF-8)
echo“Beende Skcript,aufgrund vorherige Fehler.”1>&2
;;
*)
echo“由于以前的错误而停止脚本”。“1>&2
;;
以撒
MailContent=$(journalctl-p3-o“short”--since=“$TimeStamp”--无寻呼机)
ScriptName=“${0##*/}”
SystemName=$(uname-n)
MailSubject=“${SystemName}:${ScriptName}”
echo-e“主题:${MailSubject}\n\n${MailContent}\n”| sendmail“$MailTo”
fi
出口1
}
if[!-d”${BackupDirectory}/${subdr}“]
然后
mkdir-p“${BackupDirectory}/${SubDir}”
fi
循环计数=0
OpenFiles=1
光盘/
而[“$OpenFiles”-ne 0]
做
如果[“$LoopCount”-le 180]
然后
睡眠1
OpenFiles=$(lsof$Source | wc-l)
LoopCount=$($LoopCount+1))
其他的
echo“关闭脚本。原因:由于某些文件已打开,无法创建增量备份。”1>&2
简易出口
fi
完成
tar-cpzf“$File”-g“$FileIncremental”$Source
chmod 0700“$File”
PackagesList=$(dpkg——获取选项| awk'!/deinstall |清除|保持/{print$1}'| tee“$FilePackagesList”)
而read-r PackageName
做
中的案例“$PackageName”
minidlna)
#代码。。。
;;
(拍打)
#代码。。。
;;
以撒

完成对于错误陷阱或命令替换来说,这根本不是问题,但是对于管道来说

false | true
返回
true
,除非设置了
pipefail
选项

因此,在
OpenFiles=$(lsof“$Source”| wc-l)
中,只有
wc
中的故障才会导致管道被视为故障,或者在
PackagesList=$(dpkg——获取选项| awk'!/deinstall |清除|保持/{print$1}tee“$FilePackagesList”)
,只有
tee
中的故障才会导致整个命令被视为失败



如果希望任何管道组件(而不是最后一个组件)的故障导致整个命令被视为失败,请将命令
set-o pipefail
放在脚本顶部,并注意中给出的错误陷阱的其他注意事项。

这根本不是错误陷阱的问题,或者使用命令替换,但使用管道

false | true
返回
true
,除非设置了
pipefail
选项

因此,在
OpenFiles=$(lsof“$Source”| wc-l)
中,只有
wc
中的故障才会导致管道被视为故障,或者在
PackagesList=$(dpkg——获取选项| awk'!/deinstall |清除|保持/{print$1}tee“$FilePackagesList”)
,只有
tee
中的故障才会导致整个命令被视为失败



如果希望任何管道组件出现故障(与仅最后一个组件相反),请将命令
set-o pipefail
放在脚本顶部要使整个命令被视为失败,请注意中给出的错误陷阱的其他注意事项。

另一种选择是查看管道中每个阶段的状态:

# cat test_bash_return.bash
true | true | false | true
echo "${PIPESTATUS[@]}"

# ./test_bash_return.bash
0 0 1 0

另一种选择是查看管道中每个阶段的状态:

# cat test_bash_return.bash
true | true | false | true
echo "${PIPESTATUS[@]}"

# ./test_bash_return.bash
0 0 1 0

那不是真的。失败的命令替换绝对可以触发一个错误陷阱。你能考虑提供三个你声称的案例吗?(很明显,一个我不相信的是<代码>日志CTL/<代码>命令)……注意到,Err陷阱倾向于所有的警告,归因于<代码> SET-E>代码>。(BTW,考虑<代码> PrtTf的主题:%s\n\n%s\n′$mail主题”“$mail内容”< /代码>而不是<代码> ECH-E<代码>——否则,你们都是(1)依赖于不可移植的行为[即使在bash中存在,也可以使用运行时或编译时标志关闭],(2)扩展内容中的反斜杠替换,即使它们是文本)。(另一方面,我强烈建议将
Source
设置为一个合适的数组——这样您就不会依赖
IFS
作为一个会在无引号的扩展中拆分它们的值)这是不正确的。失败的命令替换绝对可以触发一个错误陷阱。你能考虑提供一个证明所有三个你声称的案件吗?(很明显,一个我坦白地怀疑是<代码>日记CTL/COD>命令)……注意到,错误陷阱是容易的铝。