Convert a bash to ash

hello everybody,

i'm a beginner in ash and i want to convert this bash script to ash.
this script send a xml file to a nagios server :

#!/bin/bash
PROGNAME=$(basename $0)
RELEASE="Revision 0.3"

print_release() {
    echo "$RELEASE"
}
print_usage() {
    echo ""
    echo "$PROGNAME $RELEASE - Send NRPD script for Nagios"
    echo ""
    echo "Usage: send_nrdp.sh -u URL -t token [options]"
    echo ""
    echo "Usage: $PROGNAME -h display help"
    echo ""
}

print_help() {
        print_usage
        echo ""
        echo "This script is used to send NRPD data to a Nagios server"
        echo ""
        echo "Required:"
        echo "    -u","    URL of NRDP server.  Usually http://<IP_ADDRESS>/nrdp/"
        echo "    -t","    Shared token.  Must be the same token set in NRDP Server"
        echo ""
        echo "Options:"
        echo "    Single Check:"
        echo "        -H    host name"
        echo "        -s    service name"
        echo "        -S    State"
        echo "        -o     output"
        echo ""
        echo "    STDIN:"
        echo "        [-d    delimiter] (default -d \"\\t\")"
        echo "        With only the required parameters $PROGNAME is capable of"
        echo "        processing data piped to it either from a file or other"
        echo "        process.  By default, we use \t as the delimiter however this"
        echo "        may be specified with the -d option data should be in the"
        echo "        following formats one entry per line."
        echo "        For Host checks:"
        echo "        hostname    State    output"
        echo "        For Service checks"
        echo "        hostname    servicename    State    output"
        echo ""
        echo "    File:"
        echo "        -f /full/path/to/file"
        echo "        This file will be sent to the NRDP server specified in -u"
        echo "        The file should be an XML file in the following format"
        echo "        ##################################################"
        echo ""
        echo "        <?xml version='1.0'?>"
        echo "        <checkresults>"
        echo "          <checkresult type=\"host\" checktype=\"1\">"
        echo "            <hostname>YOUR_HOSTNAME</hostname>"
        echo "            <state>0</state>"
        echo "            <output>OK|perfdata=1.00;5;10;0</output>"
        echo "          </checkresult>"
        echo "          <checkresult type=\"service\" checktype=\"1\">"
        echo "            <hostname>YOUR_HOSTNAME</hostname>"
        echo "            <servicename>YOUR_SERVICENAME</servicename>"
        echo "            <state>0</state>"
        echo "            <output>OK|perfdata=1.00;5;10;0</output>"
        echo "          </checkresult>"
        echo "        </checkresults>"
        echo "        ##################################################"
        echo ""
        echo "    Directory:"
        echo "        -D /path/to/temp/dir"
        echo "        This is a directory that contains XML files in the format"
        echo "        above.  Additionally, if the -d flag is specified, $PROGNAME"
        echo "        will create temp files here if the server could not be reached."
        echo "        On additional calls with the same -D path, if a connection to"
        echo "        the server is successful, all temp files will be sent."
        exit 0
}

send_data() {
    pdata="token=$token&cmd=submitcheck&XMLDATA=$1"
    if [ ! "x$curl" == "x" ];then
        rslt=`curl -f --silent --insecure -d "$pdata" "$url/"`
        ret=$?
    else
        rslt=`wget -q -O - --post-data="$pdata" "$url/"`
        ret=$?
    fi
    status=`echo $rslt | sed -n 's|.*<status>\(.*\)</status>.*|\1|p'`
    message=`echo $rslt | sed -n 's|.*<message>\(.*\)</message>.*|\1|p'`
    if [ $ret != 0 ];then
        echo "ERROR: could not connect to NRDP server at $url"
        # verify we are not processing the directory already and then write to the directory
        if [ ! "$2" ] && [ $directory ];then
            if [ ! -d "$directory" ];then
                mkdir -p "$directory"
            fi
            # This is where we write to the tmp directory
            echo $xml > `mktemp $directory/nrdp.XXXXXX`
        fi
        exit 1
    fi
    
    if [ "$status" != "0" ];then
        # This means we couldn't connect to NRPD server
        echo "ERROR: The NRDP Server said $message"
        # verify we are not processing the directory already and then write to the directory
        if [ ! "$2" ] && [ $directory ];then
            if [ ! -d "$directory" ];then
                mkdir -p "$directory"
            fi
            # This is where we write to the tmp directory
            echo $xml > `mktemp $directory/nrdp.XXXXXX`
        fi
        
        exit 2
    fi
    
    # If this was a directory call and was successful, remove the file
    if [ $2 ] && [ "$status" == "0" ];then
        rm -f "$2"
    fi
    # If we weren't successful error
    if [ $ret != 0 ];then
        echo "exited with error "$ret
        exit $ret
    fi
}

# Parse parameters

while getopts "u:t:H:s:S:o:f:d:c:D:hv" option
do
  case $option in
    u) url=$OPTARG ;;
    t) token=$OPTARG ;;
    H) host=$OPTARG ;;
    s) service=$OPTARG ;;
    S) State=$OPTARG ;;
    o) output=$OPTARG ;;
    f) file=$OPTARG ;;
    d) delim=$OPTARG ;;
    c) checktype=$OPTARG ;;
    D) directory=$OPTARG ;;
    h) print_help 0;;
    v) print_release
        exit 0 ;;
  esac
done

if [ ! $checktype ]; then
 checktype=1
fi
if [ ! $delim ]; then
 delim=`echo -e "\t"`
fi

if [ "x$url" == "x" -o "x$token" == "x" ]
then
  echo "Usage: send_nrdp -u url -t token"
  exit 1
fi
# detecting curl 
if [[ `which curl` =~ "/curl" ]]
 then curl=1; 
fi
# detecting wget if we don't have curl
if [[ `which wget` =~ "/wget" ]]
then
    wget=1;
fi

if [[ ! $curl && ! $wget ]];
then
  echo "Either curl or wget are required to run $PROGNAME"
  exit 1
fi
checkcount=0
if [ $host ]; then
    xml=""
    # we are not getting piped results
    if [ "$host" == "" ] || [ "$State" == "" ]; then
        echo "You must provide a host -H and State -S"
        exit 2
    fi
    if [ "$service" != "" ]; then
        xml="$xml<checkresult type='service' checktype='$checktype'><servicename>$service</servicename>"
    else
        xml="$xml<checkresult type='host' checktype='$checktype'>"
    fi
    xml="$xml<hostname>$host</hostname><state>$State</state><output>$output</output></checkresult>"
    checkcount=1
fi
# Detect STDIN
########################
if [ ! -t 0 ]; then
    xml=""
    # we know we are being piped results
    IFS=$delim
    
    while read -r line ; do
        arr=($line)
        if [ ${#arr[@]} != 0 ];then
            if [[ ${#arr[@]} < 3 ]] || [[ ${#arr[@]} > 4 ]];then
                echo "ERROR: STDIN must be either 3 or 4 fields long, I found "${#arr[@]}
            else
                if [ ${#arr[@]} == 4 ]; then
                    xml="$xml<checkresult type='service' checktype='$checktype'>
                    <servicename>${arr[1]}</servicename>
                    <hostname>${arr[0]}</hostname>
                    <state>${arr[2]}</state>
                    <output>${arr[3]}</output>"
                else
                    xml="$xml<checkresult type='host' checktype='$checktype'>
                    <hostname>${arr[0]}</hostname>
                    <state>${arr[1]}</state>
                    <output>${arr[2]}</output>"
                fi
                
                xml="$xml</checkresult>"
                checkcount=$[checkcount+1]
            fi
        fi
    done
    IFS=" "
fi
if [ $host ] || [ ! -t 0 ] ;then
    xml="<?xml version='1.0'?><checkresults>$xml</checkresults>"
    send_data "$xml"
    echo "Sent $checkcount checks to $url"
fi
if [ $file ];then
    xml=`cat $file`
    send_data "$xml"
fi
if [ $directory ];then
    #echo "Processing directory..."
    for f in `ls $directory`
    do
      #echo "Processing $f file..."
      # take action on each file. $f store current file name
      xml=`cat $directory/$f`
      #echo $xml
      send_data "$xml" "$directory/$f"
    done
    
fi


any help would be appreciated

Hi.

You may wish to consider checkbashisms | SourceForge.net

Best wishes ... cheers, drl

1 Like

Thanks you for your reply, but i'm on a busybox unix.
i make little change in the script:

#!/bin/ash

PROGNAME=$(basename $0)
RELEASE="Revision 0.3"

print_release() {
    echo "$RELEASE"
}
print_usage() {
    echo ""
    echo "$PROGNAME $RELEASE - Send NRPD script for Nagios"
    echo ""
    echo "Usage: send_nrdp.sh -u URL -t token [options]"
    echo ""
    echo "Usage: $PROGNAME -h display help"
    echo ""
}

print_help() {
        print_usage
        echo ""
        echo "This script is used to send NRPD data to a Nagios server"
        echo ""
        echo "Required:"
        echo "    -u","    URL of NRDP server.  Usually http://<IP_ADDRESS>/nrdp/"
        echo "    -t","    Shared token.  Must be the same token set in NRDP Server"
        echo ""
        echo "Options:"
        echo "    Single Check:"
        echo "        -H    host name"
        echo "        -s    service name"
        echo "        -S    State"
        echo "        -o     output"
        echo ""
        echo "    STDIN:"
        echo "        [-d    delimiter] (default -d \"\\t\")"
        echo "        With only the required parameters $PROGNAME is capable of"
        echo "        processing data piped to it either from a file or other"
        echo "        process.  By default, we use \t as the delimiter however this"
        echo "        may be specified with the -d option data should be in the"
        echo "        following formats one entry per line."
        echo "        For Host checks:"
        echo "        hostname    State    output"
        echo "        For Service checks"
        echo "        hostname    servicename    State    output"
        echo ""
        echo "    File:"
        echo "        -f /full/path/to/file"
        echo "        This file will be sent to the NRDP server specified in -u"
        echo "        The file should be an XML file in the following format"
        echo "        ##################################################"
        echo ""
        echo "        <?xml version='1.0'?>"
        echo "        <checkresults>"
        echo "          <checkresult type=\"host\" checktype=\"1\">"
        echo "            <hostname>YOUR_HOSTNAME</hostname>"
        echo "            <state>0</state>"
        echo "            <output>OK|perfdata=1.00;5;10;0</output>"
        echo "          </checkresult>"
        echo "          <checkresult type=\"service\" checktype=\"1\">"
        echo "            <hostname>YOUR_HOSTNAME</hostname>"
        echo "            <servicename>YOUR_SERVICENAME</servicename>"
        echo "            <state>0</state>"
        echo "            <output>OK|perfdata=1.00;5;10;0</output>"
        echo "          </checkresult>"
        echo "        </checkresults>"
        echo "        ##################################################"
        echo ""
        echo "    Directory:"
        echo "        -D /path/to/temp/dir"
        echo "        This is a directory that contains XML files in the format"
        echo "        above.  Additionally, if the -d flag is specified, $PROGNAME"
        echo "        will create temp files here if the server could not be reached."
        echo "        On additional calls with the same -D path, if a connection to"
        echo "        the server is successful, all temp files will be sent."
        exit 0
}

send_data() {
    pdata="token=$token&cmd=submitcheck&XMLDATA=$1"
    if [  "x$curl" != "x" ];then
        rslt=`curl -f --silent --insecure -d "$pdata" "$url/"`
        ret=$?
    else
        rslt=`wget -q -O - --post-data="$pdata" "$url/"`
        ret=$?
    fi
    status=`echo $rslt | sed -n 's|.*<status>\(.*\)</status>.*|\1|p'`
    message=`echo $rslt | sed -n 's|.*<message>\(.*\)</message>.*|\1|p'`
    if [ $ret != 0 ];then
        echo "ERROR: could not connect to NRDP server at $url"
        # verify we are not processing the directory already and then write to the directory
        if [ ! "$2" ] && [ $directory ];then
            if [ ! -d "$directory" ];then
                mkdir -p "$directory"
            fi
            # This is where we write to the tmp directory
            echo $xml > `mktemp $directory/nrdp.XXXXXX`
        fi
        exit 1
    fi
    
    if [ "$status" != "0" ];then
        # This means we couldn't connect to NRPD server
        echo "ERROR: The NRDP Server said $message"
        # verify we are not processing the directory already and then write to the directory
        if [ ! "$2" ] && [ $directory ];then
            if [ ! -d "$directory" ];then
                mkdir -p "$directory"
            fi
            # This is where we write to the tmp directory
            echo $xml > `mktemp $directory/nrdp.XXXXXX`
        fi
        
        exit 2
    fi
    
    # If this was a directory call and was successful, remove the file
    if [ $2 ] && [ "$status" == "0" ];then
        rm -f "$2"
    fi
    # If we weren't successful error
    if [ $ret != 0 ];then
        echo "exited with error "$ret
        exit $ret
    fi
}

# Parse parameters

while getopts "u:t:H:s:S:o:f:d:c:D:hv" option
do
  case $option in
    u) url=$OPTARG ;;
    t) token=$OPTARG ;;
    H) host=$OPTARG ;;
    s) service=$OPTARG ;;
    S) State=$OPTARG ;;
    o) output=$OPTARG ;;
    f) file=$OPTARG ;;
    d) delim=$OPTARG ;;
    c) checktype=$OPTARG ;;
    D) directory=$OPTARG ;;
    h) print_help 0;;
    v) print_release
        exit 0 ;;
  esac
done

if [ ! $checktype ]; then
 checktype=1
fi
if [ ! $delim ]; then
 delim=`echo -e "\t"`
fi

if [ "x$url" == "x" -o "x$token" == "x" ]
then
  echo "Usage: send_nrdp -u url -t token"
  exit 1
fi
# detecting curl 
if [ `which curl` = "/curl" ]
 then curl=1; 
fi
# detecting wget if we don't have curl
if [ `which wget` = "/wget" ]
then
    wget=1;
fi

if [[ ! $curl && ! $wget ]];
then
  echo "Either curl or wget are required to run $PROGNAME"
  exit 1
fi
checkcount=0
if [ $host ]; then
    xml=""
    # we are not getting piped results
    if [ "$host" == "" ] || [ "$State" == "" ]; then
        echo "You must provide a host -H and State -S"
        exit 2
    fi
    if [ "$service" != "" ]; then
        xml="$xml<checkresult type='service' checktype='$checktype'><servicename>$service</servicename>"
    else
        xml="$xml<checkresult type='host' checktype='$checktype'>"
    fi
    xml="$xml<hostname>$host</hostname><state>$State</state><output>$output</output></checkresult>"
    checkcount=1
fi
# Detect STDIN
########################
if [ ! -t 0 ]; then
    xml=""
    # we know we are being piped results
    IFS=$delim
    
    while read -r line ; do
        arr=($line)
        if [ "${#arr[@]}" != 0 ];then
            if [[ ${#arr[@]} < 3 ]] || [[ ${#arr[@]} > 4 ]];then
                echo "ERROR: STDIN must be either 3 or 4 fields long, I found "${#arr[@]}
            else
                if [ ${#arr[@]} == 4 ]; then
                    xml="$xml<checkresult type='service' checktype='$checktype'>
                    <servicename>${arr[1]}</servicename>
                    <hostname>${arr[0]}</hostname>
                    <state>${arr[2]}</state>
                    <output>${arr[3]}</output>"
                else
                    xml="$xml<checkresult type='host' checktype='$checktype'>
                    <hostname>${arr[0]}</hostname>
                    <state>${arr[1]}</state>
                    <output>${arr[2]}</output>"
                fi
                
                xml="$xml</checkresult>"
                checkcount=$[checkcount+1]
            fi
        fi
    done
    IFS=" "
fi
if [ $host ] || [ ! -t 0 ] ;then
    xml="<?xml version='1.0'?><checkresults>$xml</checkresults>"
    send_data "$xml"
    echo "Sent $checkcount checks to $url"
fi
if [ $file ];then
    xml=`cat $file`
    send_data "$xml"
fi
if [ $directory ];then
    #echo "Processing directory..."
    for f in `ls $directory`
    do
      #echo "Processing $f file..."
      # take action on each file. $f store current file name
      xml=`cat $directory/$f`
      #echo $xml
      send_data "$xml" "$directory/$f"
    done
    
fi


but i have always this error:

ash: !: unknown operand
./send_nrdp.sh: line 206: syntax error: unexpected "(" (expecting "done")

In addition to suggested checkscript the script, there are a couple more in the original script:

 grep -En '==|\[\[|\[[0-9@]\]|=\(|\$\[|=~' script
80:    if [ ! "x$curl" == "x" ];then
118:    if [ $2 ] && [ "$status" == "0" ];then
156:if [ "x$url" == "x" -o "x$token" == "x" ]
162:if [[ `which curl` =~ "/curl" ]]
166:if [[ `which wget` =~ "/wget" ]]
171:if [[ ! $curl && ! $wget ]];
180:    if [ "$host" == "" ] || [ "$State" == "" ]; then
200:        arr=($line)
201:        if [ ${#arr[@]} != 0 ];then
202:            if [[ ${#arr[@]} < 3 ]] || [[ ${#arr[@]} > 4 ]];then
203:                echo "ERROR: STDIN must be either 3 or 4 fields long, I found "${#arr[@]}
205:                if [ ${#arr[@]} == 4 ]; then
207:                    <servicename>${arr[1]}</servicename>
208:                    <hostname>${arr[0]}</hostname>
209:                    <state>${arr[2]}</state>
210:                    <output>${arr[3]}</output>"
213:                    <hostname>${arr[0]}</hostname>
214:                    <state>${arr[1]}</state>
215:                    <output>${arr[2]}</output>"
219:                checkcount=$[checkcount+1]

replace all echo statements with:

printf "%s\n" "some line"

replace

echo -e "string"

with

printf "string"

--edit--
annotated:

80:    if [ ! "x$curl" == "x" ];then                                                             # single =
118:    if [ $2 ] && [ "$status" == "0" ];then                                                   # single =
156:if [ "x$url" == "x" -o "x$token" == "x" ]                                                    # single =
162:if [[ `which curl` =~ "/curl" ]]                                                             # use case statement test for */curl* or use type statement instead of which
166:if [[ `which wget` =~ "/wget" ]]                                                             # use case statement test for */wget* or use type statement instead of which
171:if [[ ! $curl && ! $wget ]];                                                                 # if [ ! $curl ] && [ ! $wget ]
180:    if [ "$host" == "" ] || [ "$State" == "" ]; then                                         # single =
200:        arr=($line)                                                                          # set -- $line
201:        if [ ${#arr[@]} != 0 ];then                                                          # if [ $# != 0 ]; then
202:            if [[ ${#arr[@]} < 3 ]] || [[ ${#arr[@]} > 4 ]];then                             # if [ $# -lt 3 ] || [ $# -gt 4 ]
203:                echo "ERROR: STDIN must be either 3 or 4 fields long, I found "${#arr[@]}    # printf "%s\n" "ERROR ... I found $#"
205:                if [ ${#arr[@]} == 4 ]; then                                                 # if [ $# -eq 4 ]; then
207:                    <servicename>${arr[1]}</servicename>                                     # <servicename>${2}</servicename>
208:                    <hostname>${arr[0]}</hostname>                                           # <hostname>${1}</hostname>      
209:                    <state>${arr[2]}</state>                                                 # <state>${3}</state>
210:                    <output>${arr[3]}</output>"                                              # etc...
213:                    <hostname>${arr[0]}</hostname>
214:                    <state>${arr[1]}</state>
215:                    <output>${arr[2]}</output>"
219:                checkcount=$[checkcount+1]                                                   # checkcount=$((checkcount+1))
1 Like

Hi,

thanks you for the help,
the script works manually.
i don't replace the

echo

by

printf "%s\n" 

because when i make that i don't see the error message in my log file.

the script work manually but when i put him in the crontab i have an error.
i found a subject about that :

support.nagios.com/forum/viewtopic.php?f=7&t=28397&start=10

i make the change, with that (line 200 and 231)

if [! PS1 z $]; then 

but receive this error

sh: missing ]

That looks a bit garbled, this should be:

[ ! -z "$PS1" ]

Note the spaces around the brackets...

which is equivalent to

[ -n "$PS1" ]

or

[ "$PS1" ]

But the logical counterpart of [ ! -t 0 ] would be [ -z "$PS1" ]

However,

[ ! -t 0 ]

is part of Posix so this should just work in ash. So I do not think this is a bash vs. ash matter.
If it does not work in a certain application, then it should also not work in the case of bash, unless your ash version has a bug...

1 Like

Thanks you for the answers it was an space between the " and the brackets.

everythings work fine now.

thanks you very much