I'm trying to find out if a program/script's output is being passed to eval, especially in bash scripts.

For example, can I distinguish:

$ ./program.sh


$ eval "$(./program.sh)"

within the program.sh? The latter would print the environment variables to be evaluated whereas the first one would not.

This would save me from developing a ./program.sh print-env for passing to eval.

On the other hand, I can see that having this possible potentially makes it possible to write malicious software that runs differently when it's output is passed to eval. Thoughts?

  • Yes eval is potentially dangerous, you can avoid it by all means
    – Inian
    Commented Oct 12, 2017 at 18:36
  • @Inian many tools provide set of commands for users to eval in their shell to get stuff like set up a development environment. It has a valid use case and used somewhat popularly than before nowadays. Commented Oct 12, 2017 at 22:22

1 Answer 1



eval "$(./program.sh)"

The shell would run ./program.sh with its stdout redirected to a pipe, and at the other end of the pipe would read that output in memory. And then, once ./program/sh is gone (causing eof to be seen on that pipe and the subsequent wait() done by most shell on the process to return), that saved content, minus the trailing newline character would be passed to eval.

So for ./program.sh to detect that situation, it would need to:

  1. detect that its stdout is a pipe. That's easy. On Linux, that could be with [ -p /dev/stdout ].
  2. that it's a shell process that is reading at the other end of that pipe. That becomes more complicated. On Linux with a recent lsof, you could look in the output of lsof +E -Fca -ap "$$" -d 1 for a process whose name ends with sh that has the pipe open for reading on a fd above 10.
  3. Then you would need to determine that that shell process is currently interpreting a eval something command line. For that, you'd probably need to attach a debugger to that shell and understand the internal data structures of that specific shell to see what command it is actually running.

In short you can't. But maybe you can be content with giving a different output when the output goes to a tty and when not, which should just be a matter of:

if [ -t 1 ]; then
  echo output for tty
  echo output for something else
  • Actually the "is TTY" check seems to be working just fine for eval. I understand that it work also cover piping to another process or redirecting to a file, but I think it covers the non-interactive state, so I think it's good enough! Thank you. Commented Oct 12, 2017 at 22:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .