Re: bash redirection stdout and stderr - pipeline command causes subshell execution
From: Netocrat (netocrat_at_dodo.com.au)
Date: 09/04/05
- Previous message: John Savage: "Re: Capitalising file names - is this possible with sed?"
- In reply to: S. Anthony Sequeira: "bash redirection stdout and stderr - pipeline command causes subshell execution"
- Next in thread: S. Anthony Sequeira: "Re: bash redirection stdout and stderr - pipeline command causes subshell execution"
- Reply: S. Anthony Sequeira: "Re: bash redirection stdout and stderr - pipeline command causes subshell execution"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Sun, 04 Sep 2005 13:18:17 +1000
On Fri, 02 Sep 2005 23:05:50 +0100, S. Anthony Sequeira wrote:
> Hi,
>
> Hope I piqued your interest with the subject.
You did. I've just become aware of this issue myself.
> I will try to be clear.
>
> I have a function which executes several commands.
>
> It is called thus:
>
> { function 3>&1 1>&2 2>&3 | tee function.err } &> function.log
>
> This works fine, inasmuch it produces a logfile with just the errors,
> and another with both stdout and stderr interleaved, for further
> investigation of anything in the error log.
>
> The problem is when one or more of the commands sets a variable which
> should be available further down the script, or when a cd is done within
> the function, again required later.
>
> My research (man pages and google) indicate that a pipe symbol causes
> commands to be executed in a subshell. This causes any environmental
> alterations in the function not to be propagated to the rest of the
> script.
Bash's manpage documents this behaviour for "simple command[s] other than
a builtin or shell function" and also "[c]ommand substitution, commands
grouped with parentheses, and asynchronous commands ... Builtin commands
that are invoked as part of a pipeline are also executed in a subshell
environment."
This is pretty similar to the POSIX shell spec at
http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_12
which is not surprising given that bash is a POSIX shell.
However the POSIX spec adds:
"Additionally, each command of a multi-command pipeline is in a subshell
environment; as an extension, however, any or all commands in a pipeline
may be executed in the current environment."
A little ambiguous for a specification... and yes, bash chooses not to
offer this extension as you have discovered.
This leads to undesirable inconsistency. The fish shell deals with this
issue by never forking a new shell instance, thus ensuring consistency and
slightly better (but probably unnoticably) execution times. If you want
a distinct subshell environment in fish, you must explicitly run a new
shell interpreter.
You might find fish useful in your situation, with the caveat that
redirecting fds other than 0, 1, 2 is somewhat broken in the current
release. Also redirection currently works at pipeline level rather than
individual process level, so you'd have to wrap the function call
redirections in another block, something like:
{ { function 3>&1 1>&2 2>&3 } | tee function.err } &> function.log
except that the fish syntax is slightly different - it doesn't support
braces so you'd have to use an "if true" block. There's discussion of
adding a block operator.
Even though written after the standard, fish deviates from POSIX in many
other ways, largely to improve and simplify shell syntax from the author's
point of view; his philosophy is that for portable POSIX scripting bash is
available and therefore fish is free to improve on POSIX's syntax. Its
focus is on user-friendliness and interactive use and it contains some
neat ideas with development ongoing. One useful addition to fish is
variable scoping; scope is local by default.
> I have been attempting to find a construct that will duplicate the
> logging facility, without operating in a subshell, in vain. I can place
> any such commands outside the function call, but this is not ideal, as I
> lose the logging.
You could pass the logging filenames into the function and perform the
redirections and tee on each command within the function, but that would
be pretty inconvenient. Perhaps other shells (ksh, zsh) have chosen not
to fork in this situation and you could use one of them instead, but I
suspect that they would do the same.
> Any ideas please?
Well you needn't perform the environment-changing commands within the
function; in your later post you say that logging would be lost in that
case, but what logging do you want to perform on changing a directory or
setting a variable? And if you do need to log such things, what's
stopping you?
> Cheers.
-- http://members.dodo.com.au/~netocrat
- Previous message: John Savage: "Re: Capitalising file names - is this possible with sed?"
- In reply to: S. Anthony Sequeira: "bash redirection stdout and stderr - pipeline command causes subshell execution"
- Next in thread: S. Anthony Sequeira: "Re: bash redirection stdout and stderr - pipeline command causes subshell execution"
- Reply: S. Anthony Sequeira: "Re: bash redirection stdout and stderr - pipeline command causes subshell execution"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|