2

I have this code in a bash script:

r2g(){

   echo "executable is: $0"  # "/bin/bash"

  (
      set -e;
      r2g_internal "$@" \
       2> >( while read line; do echo "r2g error: $line"; done ) \
       1> >( while read line; do echo "r2g: $line"; done )
  )

    exit_code="$?"
    if [[ "$exit_code" != "0" ]]; then
        echo "something experienced an error, to see log, run: r2g_view_log";
        return 1;
    fi
}

what's happening is that after r2g_internal runs, sh is launched by some process and it apparently tries to resource the bash env, and I get his weird syntax error from sh:

r2g error: sh: r2g: line 2: syntax error near unexpected token `>'
r2g error: sh: r2g: line 2: ` r2g_internal "$@" 2> >( while read line; do echo "r2g error: $line"; done ) > >( while read line; do echo "r2g: $line"; done ) );'
r2g error: sh: error importing function definition for `r2g'

I made a video demoing the problem: https://www.useloom.com/share/82f23ebfe6754412a20be057957e45f4

and a follow up vid: https://www.useloom.com/share/0465c2857cc244879b52b7bdb516243e

when npm install runs, some sh process must be launched by npm..git also seems to launch an sh process sometimes when I run git commands, and the same type of syntax errors show up in the terminal in that case.

I cannot figure out why a sh process launched via bash would then try to source some of the bash code from the parent shell/env?

The video makes the problem clearer (I hope).

if I call unset -f r2g, the problem goes away immediately. So I guess /bin/sh is calling my r2g function, but I don't know how or why.

Here is the source for r2g and r2g_internal together: https://gist.github.com/ORESoftware/0fa7e3d6b75a65b17b6b126a7bec3397

2 Answers2

3

This won't probably solve your problem, just take a moment for a few notes, too long for a comment:

  • If you don't need to do so, don't structure your code as a single line, I am quoting:

    r2g_internal "$@"  2> >( while read line; do echo "r2g error: $line"; done ) 1> >( while read line; do echo "r2g: $line"; done )
    

    It is unreadable for others and even to you I suspect.

  • I'll start from the beginning:

    I don't see a shebang like:

    #!/bin/bash
    

    or

    #!/bin/sh
    

    and so on.

  • If you don't need Bash, but this shell script seems to need it, use POSIX sh for portability purposes.

  • Since exit_code is used only once, you can avoid it.

  • You don't need to quote what number always is. In this instance "$?".

  • Avoid Bash-specific [[ .. ]], and use classic test command instead. In this instance:

    if [ $? -ne 0 ]
    
  • You don't need a semi-colon at the end of the line, you may use structure like this one:

    if [ $? -ne 0 ]
    then
        echo "something experienced an error, to see log, run: r2g_view_log"
        return 1
    fi
    
  • Use -r switch with read. Read more about this topic here.

  • I made a few other adjustments, check it out, please.

  • I'm unsure, if that is intentional, but I will suppose not; where you used return 1, from what I can see, should be exit 1.

  • The shebang can contain the set -e as follows:

    #!/bin/bash -e
    

Rewritten based on above:

#!/bin/bash -e

r2g()
{

    echo "executable name is: $0"

    r2g_internal "$@" 2> >( while read -r line; do echo "r2g error: $line"; done ) >( while read -r line; do echo "r2g: $line"; done )

    if [ $? -ne 0 ]
    then
        echo "something experienced an error, to see log, run: r2g_view_log"
        exit 1
    fi

}
  • if i use set -e globally and it gets set in my shell, any command that exits with non zero will close the terminal window. this script is getting sourced by all bash shells so.. – Alexander Mills May 10 '18 at 16:47
  • the shebang/hashbang also doesnt matter. that wont determine which process calls the function. – Alexander Mills May 10 '18 at 16:48
-1

No offence but have you tried to read and understand error message:

syntax error near unexpected token `>'

It explicitly tells that your code contains obvious error: 2> >(. '>' is to direct standard output into file. Your are trying to direct output of r2g_internal to script reading from standard input. You must use '|' not '>'.

And one more error -- you can direct stdout and stderr to separate files but you can not easily direct them to separate scripts. You will have to write them first into files and then process them separately.

r2g_internal "$@" 1> stdout.txt 2> stderr.txt
cat stderr.txt | ( while read line; do echo "r2g error: $line"; done )
cat stdout.txt | ( while read line; do echo "r2g: $line"; done )
John Doe
  • 423
  • 1
    Note that using process substitution (>(...)) is exactly what he wants to be doing to filter the output from r2g_internal as it arrives. – Kusalananda May 09 '18 at 15:24
  • Although process substitution is available only in ksh bash zsh -- and bash not when POSIX mode, which may be the cause of the error message. Cf https://unix.stackexchange.com/questions/309547/what-is-the-portable-posix-way-to-achieve-process-substitution – dave_thompson_085 May 10 '18 at 06:47
  • well it says it's sh that is barfing on the syntax – Alexander Mills May 19 '18 at 07:58