1
votes

Perhaps BASH differences? Worked fine in old server, not working in new.

It never echos "made it" in the get_running_palaces() function but instead outputs

comm: /dev/fd/63: No such file or directory
comm: /dev/fd/63: No such file or directory

#!/bin/bash

TYPE=$1

get_palaces(){
    for PALACE in $(ls -trI shared /home | sort); do
        if [ -d "/home/$PALACE/palace" ]; then
            echo $PALACE
        fi
    done
}
#  comm -12 file1 file2  Print only lines present in both file1 and file2.
# comm -3  file1 file2  Print lines in file1 not in file2, and vice vers
get_running_palaces(){
    echo "made it";
    PSFRONT_A=$(ps ax | grep '[p]sfront -p .* -r /home/.*/palace ' |  sed 's| *\([0-9]*\).*/home/\(.*\)/palace.*$|\2|' | uniq | sort)
    PSERVER_A=$(ps ax | grep '[p]server.* -f /home/.*/palace/psdata/pserver.conf ' | sed 's| *\([0-9]*\).*/home/\(.*\)/palace.*$|\2|' | sort)
    ERRORS=$(comm -3 <(echo "${PSERVER_A[*]}") <(echo "${PSFRONT_A[*]}"))
    if [ ! -z "$ERRORS" ]; then
        comm -3 <(echo "${PSERVER_A[*]}") <(echo "${ERRORS[*]}")
    else
        echo "$PSERVER_A"
    fi

}

case "$TYPE" in
online) 
    KNOWN_PALACES=$(get_palaces)
    ERROR_LESS=$(get_running_palaces)
    ONLINE=$(comm -12 <(echo "${KNOWN_PALACES[*]}") <(echo "${ERROR_LESS[*]}"))

    [ ! -z "$ONLINE" ] && echo "$ONLINE"
    ;;
offline)    
    KNOWN_PALACES=$(get_palaces | sort)
    ERROR_LESS=$(get_running_palaces)

    OFFLINE=$(comm -3 <(echo "${KNOWN_PALACES[*]}") <(echo "${ERROR_LESS[*]}"))

    [ ! -z "$OFFLINE" ] && echo "$OFFLINE"
    ;;
*)  
    get_palaces
    ;;
esac


exit 0;

Information:

New server:


uname -a
Linux www.ipalaces.org 2.6.32-274.7.1.el5.028stab095.1 #1 SMP Mon Oct 24 20:49:24 MSD 2011 x86_64 GNU/Linux
lsb_release -rd
-bash: lsb_release: command not found
bash --version
GNU bash, version 4.1.5(1)-release (x86_64-pc-linux-gnu)


Old server:

uname -a
Linux ipalaces.org 2.6.32-5-686 #1 SMP Mon Jan 16 16:04:25 UTC 2012 i686 GNU/Linux
lsb_release -rd
Description: Debian GNU/Linux 6.0.4 (squeeze)
Release: 6.0.4

bash --version
GNU bash, version 4.1.5(1)-release (i486-pc-linux-gnu)

2
What are the differences between the servers? The error message looks vaguely like you have the right Bash version, but the underlying architecture doesn't support the process substitutions ... maybe. Output of uname -a, lsb_release -rd, bash --version etc might be useful for diagnostics. - tripleee
@tripleee done. Checkout edit - ParoX
@tripleee it should also be noted that ps ax | grep '[p]sfront -p .* -r /home/.*/palace ' | sed 's| *\([0-9]*\).*/home/\(.*\)/palace.*$|\2|' | uniq | sort and ps ax | grep '[p]server.* -f /home/.*/palace/psdata/pserver.conf ' | sed 's| *\([0-9]*\).*/home/\(.*\)/palace.*$|\2|' | sort work as should on both servers. - ParoX
What does comm do? Your new server appears to be an OpenVZ container, and will not have access to many kernel functions. - jordanm
@jordanm: comm is a standard file comparison utility. - tripleee

2 Answers

1
votes

Process substitution requires /dev/fd/* on Linux (how it's implemented varies on how Bash is built, I think). Maybe you have a screwed up /dev/ structure at the point where this script is running? Stuff like that happens.

I've seen boot-time bash scripts fail from trying to generate a here document, which required /tmp which wasn't mounted yet (and would come from tmpfs later, so there is no such directory in the root volume or anywhere else).

Does process substitution work at all on that system? I mean if you log in to a system that is up and running, can you do things like

diff <(echo "a") <(echo "b")

?

If that doesn't work, you either have to fix /dev, or change how Bash is built (get it to uses fifos for process substitution) or just change your script not to rely on process substitution.

0
votes

If you cannot figure out how to enable process substitution in Bash on the new server, perhaps you should refactor the script to use a more traditional processing model. Basically, that boils down to using temporary files.

ps ax |
grep '[p]sfront -p .* -r /home/.*/palace ' |
sed 's| *\([0-9]*\).*/home/\(.*\)/palace.*$|\2|' |
uniq | sort >/tmp/PSFRONT_A

ps ax |
grep '[p]server.* -f /home/.*/palace/psdata/pserver.conf ' |
sed 's| *\([0-9]*\).*/home/\(.*\)/palace.*$|\2|' |
sort >/tmp/PSERVER_A

ERRORS=$(comm -3 /tmp/PSERVER_A /tmp/PSFRONT_A)

rm /tmp/PSERVER_A /tmp/PSFRONT_A

Incidentally, this is completely POSIX compatible, so you could change the shebang line to #!/bin/sh while you are at it.

You should simplify the grep | sed and refactor the recurring functionality; also, proper use of temporary files calls for the use of a trap to remove the temporary files even if the script is interrupted by a signal midway through.

t=`mktemp -t -d palaces.XXXXXXXX` || exit 127
trap 'rm -rf $t' 0
trap 'exit 126' 1 2 3 5 15

psg () {
    local re
    re=$1
    ps ax |
    sed -n "\\%$re%"'s| *\([0-9]*\).*/home/\(.*\)/palace.*$|\2|p'
}

psg '[p]sfront -p .* -r /home/.*/palace ' |
    uniq | sort >$t/PSFRONT_A
psg '[p]server.* -f /home/.*/palace/psdata/pserver\.conf ' |
    sort >$t/PSERVER_A

comm -3 $t/PSERVER_A $t/PSFRONT_A >$t/ERRORS

if [ -s $t/ERRORS ]; then
    comm -3 $t/PSERVER_A $t/ERRORS
else
    cat $t/PSERVER_A
fi

The rest of the script can be adapted accordingly.