Bash conditional piping

后端 未结 3 1632
野趣味
野趣味 2021-01-13 03:13

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 --passp         


        
相关标签:
3条回答
  • 2021-01-13 03:38

    The following code should conditionally pipe the result if the file opens successfully:

       result=open "$@" "$PASSWORD"
        if [ $? -gt 0 ]; then
          exit 1
        fi
        echo "$result" | <SOMECOMMAND>
    
    0 讨论(0)
  • 2021-01-13 03:43

    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.

    0 讨论(0)
  • 2021-01-13 03:50

    Use a named pipe and store the return value

    mkfifo piper;
    open "$@" "$PASSWORD"; retval=$? > piper &
    if [ x"$retval" != x0 ]
    then
       rm piper
       exit 1
    fi
    <SOMECOMMAND> < piper
    rm piper
    
    0 讨论(0)
提交回复
热议问题