5

我如何通过管道输出命令以防万一它返回 true?

function open
{
    TEMPFILE=$(mktemp -u)
    if ! gpg2 --quiet --decrypt --batch --passphrase "$2" "$1" 2> $TEMPFILE; then
        error $"Password errata od errore di lettura dal file\n\nDettagli:\n$(grep -v '^$' $TEMPFILE)"
        rm -f $TEMPFILE
        return 1
    fi
    rm -f $TEMPFILE
}

if ! open "$@" "$PASSWORD"; then
    exit 1
fi | <SOMECOMMAND>

这样,它只是管道并且不检查 open 是返回 true 还是 false,因此永远不会执行“exit 1”。

如何在不使用文件的情况下解决它(出于安全原因)。

4

3 回答 3

9

在我提出解决方案之前,让我解释一下这比您意识到的更困难。基本问题是时间:open ...函数在运行时产生输出;它在完成运行后(因此在它产生输出之后)产生退出状态。由于您希望根据退出状态对输出执行不同的操作,因此您必须将输出临时存储在某个地方,直到函数完成,您可以决定如何处理输出。

管道本身不适用于此,因为管道不存储数据(除了一点缓冲区空间)-它们将数据“实时”从一个程序传递到另一个程序,在这种情况下,第二个程序无法启动直到第一个完成之后。通常,临时文件将是完美的(存储数据是文件的用途),但出于安全原因,您不希望这样做。这几乎是将数据放在 RAM 中的某个位置(尽管这也不是完全安全的......)。

@Karoly Horvath 的回答建议将输出存储在 bash 变量中(存储在 RAM 中),但这不起作用,因为 bash 无法处理变量值中的空字节。因此,我提出了一种变体,您可以在其中使用数据的“安全”编码,并将其放入 bash 变量中。我使用 uuencode 格式,但您也可以使用 base64、十六进制转储等...

if result=$(open "$@" "$PASSWORD" | uuencode -; exit ${PIPESTATUS[0]}); then
    echo "$result" | uudecode -p | SOMECOMMAND
fi

请注意,PIPESTATUS 是一个 bashism,因此您应该以#!/bin/bash. 此外,如果输出太长,您可能会遇到 bash 想要存储/扩展/等多少数据的限制;如果这被证明是一个问题,事情就会变得更加复杂。

顺便说一句,如果您担心安全性,请不要使用 gpg2 的--passphrase选项——在命令行上传递密码短语会将其暴露给例如ps在正确时间运行的任何人,这是一个非常糟糕的主意。gpg2 有许多提供密码的选项,所以请使用更好的选项。

于 2012-05-02T16:10:45.040 回答
0

如果文件成功打开,则以下代码应有条件地通过管道传输结果:

   result=open "$@" "$PASSWORD"
    if [ $? -gt 0 ]; then
      exit 1
    fi
    echo "$result" | <SOMECOMMAND>
于 2012-05-02T11:44:15.733 回答
0

使用命名管道并存储返回值

mkfifo piper;
open "$@" "$PASSWORD"; retval=$? > piper &
if [ x"$retval" != x0 ]
then
   rm piper
   exit 1
fi
<SOMECOMMAND> < piper
rm piper
于 2012-05-02T14:34:04.643 回答