2

I have a bash script that sources contents from another file. The contents of the other file are commands I would like to execute and compare the return value. Some of the commands are have multiple commands separated by either a semicolon (;) or by ampersands (&&) and I can't seem to make this work. To work on this, I created some test scripts as shown:

test.conf is the file being sourced by test

Example-1 (this works), My output is 2 seconds in difference

test.conf

    CMD[1]="date"

test.sh

    . test.conf
    i=2
    echo "$(${CMD[$i]})"
    sleep 2
    echo "$(${CMD[$i]})" 

Example-2 (this does not work) test.conf (same script as above)

    CMD[1]="date;date"

Example-3 (tried this, it does not work either) test.conf (same script as above)

    CMD[1]="date && date"

I don't want my variable, CMD, to be inside tick marks because then, the commands would be executed at time of invocation of the source and I see no way of re-evaluating the variable.

This script essentially calls CMD on pass-1 to check something, if on pass-1 I get a false reading, I do some work in the script to correct the false reading and re-execute & re-evaluate the output of CMD; pass-2.

Here is an example. Here I'm checking to see if SSHD is running. If it's not running when I evaluate CMD[1] on pass-1, I will start it and re-evaluate CMD[1] again.

test.conf

    CMD[1]=`pgrep -u root -d , sshd 1>/dev/null; echo $?`

So if I modify this for my test script, then test.conf becomes: NOTE: Tick marks are not showing up but it's the key below the ~ mark on my keyboard.

    CMD[1]=`date;date` or `date && date`

My script looks like this (to handle the tick marks)

    . test.conf
    i=2
    echo "${CMD[$i]}"
    sleep 2
    echo "${CMD[$i]}"

I get the same date/time printed twice despite the 2 second delay. As such, CMD is not getting re-evaluate.

2
  • 1
    Your question isn't clear - actually, I don't see the question. What exactly is are you trying to do, and where does it go wrong? Your "example", "test.conf CMD[1]=pgrep -u"... makes precious little sense - where is the "source file"? How are you parsing arguments - you're missing quotes as I see it? Commented Jul 13, 2009 at 18:28
  • This is a test script, not the actual. Hence the reason the $i is still in there (cut -n- past) and this is lacking in clarity. The CMD[x] where x = 0 ... 10 are test conditions that return either 1 or 0; mostly is the process running or not and similar to the pgrep example given above. Along with CMD, I have a corresponding RESTART[x] that I call and after I call it, I re-evaluate the CMD[x] to see if the process restarted. In other examples I am checking for presence of a log file. I didn't want to bore the forum with these details but it would probably have been helpful. Thank you! Commented Jul 14, 2009 at 12:16

2 Answers 2

2

First of all, you should never use backticks unless you need to be compatible with an old shell that doesn't support $() - and only then.

Secondly, I don't understand why you're setting CMD[1] but then calling CMD[$i] with i set to 2.

Anyway, this is one way (and it's similar to part of Barry's answer):

CMD[1]='$(date;date)'    # no backticks (remember - they carry Lime disease)
eval echo "${CMD[1]}"    # or $i instead of 1
Sign up to request clarification or add additional context in comments.

3 Comments

This also works. I hadn't thought of this method. Excellent, Thank You!
Do I understand right, that CMD[1] then holds already the outputs of the commands and not the commands itself?
@MattTT: No, it contains the commands because the assignment uses single quotes. The eval executes the commands. This question and answer pertain to a specific set of circumstances and aren't intended to be generally applicable. If you came here trying to solve a problem, there's probably a better way to do it.
1

From the couple of lines of your question, I would have expected some approach like this:

#!/bin/bash

while read -r line; do
    # munge $line
    if eval "$line"; then
        # success
    else
        # fail
    fi
done

Where you have backticks in the source, you'll have to escape them to avoid evaluating them too early. Also, backticks aren't the only way to evaluate code - there is eval, as shown above. Maybe it's eval that you were looking for?

For example, this line:

CMD[1]=`pgrep -u root -d , sshd 1>/dev/null; echo $?`

Ought probably look more like this:

CMD[1]='`pgrep -u root -d , sshd 1>/dev/null; echo $?`'

1 Comment

This works! However, per my and your earlier comments (we agree) I don't want back ticks in there. This script will not live on any other environments outside of Linux, I have no control over BASH and agree with your portability concern!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.