Eddified
Eddified

Reputation: 3154

Why is my output going to stdout and not to file?

I have a script like this:

#!/usr/bin/bash
COMMAND='some_command >> some_log_file 2>&1'
until $COMMAND; do
    echo "some_command crashed with exit code $?.  Respawning.." >&2
    sleep 1
done

(I got the until ... done bit from https://stackoverflow.com/a/697064/88821 , FWIW, but changed it a bit.)

While some_command is being run, the problem is that the output is not going to some_log_file. Instead, it goes to the stdout of the shell from which I ran this wrapper script. How can I get the output to go to some_log_file while keeping the entire command (including redirects) in the variable COMMAND? The idea is to use this script as a more general wrapper script that can be used with other programs. (COMMAND is actually being passed as an argument into the script).

Upvotes: 0

Views: 57

Answers (2)

Charles Duffy
Charles Duffy

Reputation: 295288

You're passing >> some_log_file 2>&1 as arguments to some_command, rather than honoring them as redirections. This happens because parsing shell syntax (such as redirections) happens before parameter expansions are performed (the point in processing where $foo is replaced with the contents of the relevant variable). That's actually desirable behavior -- it would be impossible to write code in shell handling untrusted data otherwise.

Don't store code in strings. You can include it literally:

until some_command >> some_log_file 2>&1; do
    echo "some_command crashed with exit code $?.  Respawning.." >&2
    sleep 1
done

...or you can store it in a function:

mycode() { some_command >> some_log_file 2>&1; }

until mycode; do
    echo "some_command crashed with exit code $?.  Respawning.." >&2
    sleep 1
done

Upvotes: 1

Wilfredo Pomier
Wilfredo Pomier

Reputation: 1121

One way is

#!/usr/bin/bash
COMMAND='some_command >> some_log_file 2>&1'
until bash -c "$COMMAND"; do
    echo "some_command crashed with exit code $?.  Respawning.." >&2
    sleep 1
done

The problem with your approach is that it does not evaluate the variable as bash code, but just as a series of literal strings. It's like how putting "1+1" in a Java string will never cause 2 to be printed without invoking a Java interpreter:

String cmd="1+1";
System.out.println(cmd);  // Prints 1+1
System.out.println(1+1);  // Prints 2

Upvotes: 0

Related Questions