Bash有条件的管道 [英] Bash conditional piping

查看:125
本文介绍了Bash有条件的管道的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 函数打开
{b>}如何输出命令的输出以防万一它返回true?
TEMPFILE = $(mktemp -u)
if! gpg2 --quiet --decrypt --batch --passphrase$ 2$ 12> $ TEMPFILE;然后
错误$密码错误错误日志文件\\\
\\\
Dettagli:\ $ $(grep -v'^ $'$ TEMPFILE)
rm -f $ TEMPFILE
返回1
fi
rm -f $ TEMPFILE
}

if!打开$ @$ PASSWORD;那么
出口1
fi | < SOMECOMMAND>

这样,它只是管道,不检查open是否返回true或false,所以不会执行exit 1。



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

解决方案

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



一个管道固有地不会为此工作,因为管道不会存储数据(除了一点缓冲区空间) - 它们将数据从一个程序传送到另一个程序,在这种情况下,第二个程序可以直到第一次结束后才开始。通常情况下,一个临时文件将是完美的(存储数据是什么文件),但你不希望出于安全原因。这几乎把留下的数据放在RAM的某个地方(尽管这不是完全安全的......)。

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

  if result = $(open $ @$ PASSWORD| uuencode  - ; exit $ {PIPESTATUS [0]});那么
会回显$ result| uudecode -p | SOMECOMMAND
fi

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

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


How can I pipe an output of a command just in case it returns 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>

This way, it just pipe and don't check whether open returns true or false so doesn't ever execute "exit 1".

How can I solve it without using files (for security reasons).

解决方案

Before I propose a solution, let me explain any this is more difficult than you realize. The basic problem is timing: the open ... function produces output as it runs; it produces an exit status after it has finished running (and hence after it has produced its output). Since you want to do different things with the output depending on the exit status, you must store the output someplace temporary until the function finishes and you can decide what to do with the output.

A pipe inherently won't work for this, because pipes don't store data (except for a little buffer space) -- they pass data "live" from one program to another, and in this case the second program can't start until after the first has finished. Normally, a temp file would be perfect for this (storing data is what files are for), but you don't want that for security reasons. That pretty much leaves putting the data somewhere in RAM (although that's not perfectly secure either...).

@Karoly Horvath's answer proposed storing the output in a bash variable (which is stored in RAM), but that didn't work because bash doesn't cope with null bytes in variable values. So, I propose a variant where you use a "safe" encoding of the data, and put that in a bash variable. I used uuencode format, but you could also use base64, hex dump, etc...

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

Note that PIPESTATUS is a bashism, so you should start the script with #!/bin/bash. Also, if the output is too long you may run into limits on how much data bash wants to store/expand/etc; if that turns out to be a problem, things get more complicated.

BTW, if you're concerned about security, don't use gpg2's --passphrase option -- passing the passphrase on the command line exposes it to e.g. anyone who runs ps at the right time, which is a very bad idea. gpg2 has many options for supplying the passphrase, so please use a better one.

这篇关于Bash有条件的管道的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆