LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 02-25-2015, 10:25 AM   #1
mdijoux25
LQ Newbie
 
Registered: Feb 2015
Posts: 2

Rep: Reputation: Disabled
Smile 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 (it's not by me)
i'm on a busybox unix (synology).

Code:
#!/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
 
Old 02-25-2015, 10:28 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,869
Blog Entries: 1

Rep: Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870
Just change first line to #!/bin/ash and see what happens.
 
Old 02-25-2015, 10:33 AM   #3
mdijoux25
LQ Newbie
 
Registered: Feb 2015
Posts: 2

Original Poster
Rep: Reputation: Disabled
thanks for your reply.
i make that change but receive this error :
Code:
ash: =~: unknown operand
ash: !: unknown operand
./send_nrdp.sh: line 206: syntax error: unexpected "(" (expecting "done")
i make little change :

Code:
#!/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:

Code:
ash: !: unknown operand
./send_nrdp.sh: line 206: syntax error: unexpected "(" (expecting "done")
 
Old 02-25-2015, 10:56 AM   #4
veerain
Senior Member
 
Registered: Mar 2005
Location: Earth bound to Helios
Distribution: Custom
Posts: 2,524

Rep: Reputation: 319Reputation: 319Reputation: 319Reputation: 319
ash doesn't supports =~ operator. You may use 'grep -E' instead.
 
Old 02-25-2015, 11:08 AM   #5
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,869
Blog Entries: 1

Rep: Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870
There's no arrays in ash. Only the arguments can be used sort-of array-like:

Code:
read line
set -- $line
# now $1,$2, $3..., $#, $*, $@ are set
 
Old 02-25-2015, 12:26 PM   #6
metaschima
Senior Member
 
Registered: Dec 2013
Distribution: Slackware
Posts: 1,982

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
Run this tool:
http://sourceforge.net/projects/checkbaskisms/

with the posix and extended options. It will help detect non-posix bashisms.
 
Old 02-25-2015, 12:31 PM   #7
mina86
Member
 
Registered: Aug 2008
Distribution: Debian
Posts: 517

Rep: Reputation: 229Reputation: 229Reputation: 229
A few comments not all aimed at compatibility:

Quote:
Code:
    echo ""
You might find here-doc easier to use than bunch of echos, e.g.:
Code:
cat <<EOF

$PROGNAME $RELEASE - Send NRPD script for Nagios

Usage: send_nrdp.sh -u URL -t token [options]

Usage: $PROGNAME -h display help

EOF
Quote:
Code:
if [ ! "x$curl" == "x" ];then
‘==’ is not a POSIX operator, ‘=’ is. Furthermore, using ‘!’ and ‘=’ is a bit weird, just use ‘!=’. Lastly, in this particular case, you could just use ‘-z’, e.g.:
Code:
if [ -z "$curl" ]; then
Quote:
Code:
status=`echo $rslt | sed -n 's|.*<status>\(.*\)</status>.*|\1|p'`
Prefer $(…) to `…` but in this instance, more importantly, always quote your variables. For example, observe:
Code:
$ a='/*'
$ echo $a
/bin /boot /dev /etc /home /lib /lib32 /lib64 /lost+found /media /mnt /proc /root /run /sbin /sys /tmp /usr /var
Quote:
Code:
if [ $ret != 0 ];
Prefer -ne and -eq for numeric comparison.

Quote:
Code:
if [ ! "$2" ] && [ $directory ];then
Again, always quote variables. Furthermore, I would recommend using explicit ‘-z’ and ‘-n’ operators. They have fewer compatibility problems and are a bit less confusing. So the above line becomes:
Code:
if [ -z "$2" ] && [ -v "$directory" ]; then
Quote:
Code:
            if [ ! -d "$directory" ];then
                mkdir -p "$directory"
            fi
The condition is actually unnecessary.

Quote:
Code:
if [ "x$url" == "x" -o "x$token" == "x" ]
If you’re really worired about compatibility, you might find using || and && better, e.g.:
Code:
if [ -z "$url" ] || [ -z "$token" ]
Quote:
Code:
if [[ ! $curl && ! $wget ]];
[[ … ]] is bash, use [ … ], e.g.:
Code:
if [ -z "$curl" ! || [ -z "$wget" ];
Quote:
Code:
if [ ! -t 0 ]; then
It’s more portable to use shell negation rather than relying on test implementing negation, as in:
Code:
if ! [ -t 0 ]; then
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
ash instead of bash -- getting it to work by hand after installation scmaccal Slackware 16 04-20-2014 02:42 PM
[SOLVED] Bash to ash: Help converting a script? Mouse750 Programming 7 09-08-2011 01:32 PM
Best way to convert this (bash) to c? primerib Programming 4 03-20-2010 02:30 PM
Use bash as an alternative to ash? J_Szucs Linux - General 3 05-30-2005 04:44 AM
Sarge - only ASH in shell no BASH jriis Debian 1 12-25-2003 03:25 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:24 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration