46

I'm still very new to scripting in bash, and just trying a few what I thought would be basic things. I want to run DDNS that updates from the my server running Ubuntu 14.04.

Borrowing some code from dnsimple, this is what I have so far:

#!/bin/bash

LOGIN="email"
TOKEN="token"
DOMAIN_ID="domain"
RECORD_ID="record"
IP=`curl -s http://icanhazip.com/`

OUTPUT=`
curl -H "Accept: application/json" \
     -H "Content-Type: application/json" \
     -H "X-DNSimple-Domain-Token: $TOKEN" \
     -X "PUT" \
     -i "https://api.dnsimple.com/v1/domains/$DOMAIN_ID/records/$RECORD_ID" \
     -d "{\"record\":{\"content\":\"$IP\"}}"`

if ! echo "$OUTPUT" | grep -q "(Status:\s200)"; then

echo "match"

$(echo "$OUTPUT" | grep -oP '(?<="message":")(.[^"]*)' >> /home/ddns/ddns.log)
$(echo "$OUTPUT"| grep -P '(Status:\s[0-9]{3}\s)' >> /home/ddns/ddns.log)

fi

The idea is that it runs every 5 minutes, which I have working using a cronjob. I then want to check the output of the curl to see if the status is "200" or other. If it is something else, then I want to save the output to a file.

What I can't get working is the if statement. As I understand it, the -q on the grep command will provide an exit code for the if statement. However I can't seem to get it work. Where have I gone wrong?

4
  • Does your script work if you remove the if check and always echo to the log file? dnssimple shows a $LOGIN before $TOKEN, but you're missing that. Maybe that's causing things to fail?
    – Mikel
    Apr 9 '16 at 19:10
  • 1
    I've slightly modified it. I'm using a DNSimple-Domain-Token which doesn't need the LOGIN variable. Apr 9 '16 at 19:31
  • if i were you, i'd run this only when the internet network interface goes up rather than every 5 minutes from cron. or, at least, cache "$IP" in a file somewhere (perhaps /var/tmp/icanhazip) and if it hasn't changed since the last run, exit 0 before doing anything else. you don't need to update your DDNS entry every 5 minutes, only when your IP address changes.
    – cas
    Apr 10 '16 at 0:03
  • Good idea - I will work on adding that. Apr 12 '16 at 8:29
72

You're almost there. Just omit the exclamation mark:

OUTPUT='blah blah (Status: 200)'
if echo "$OUTPUT" | grep -q "(Status:\s200)"; then
    echo "MATCH"
fi

Result:

MATCH

The if condition is fulfilled if grep returns with exit code 0 (which means a match). The ! exclamation mark will negate this.

2
  • For some reason this didn't work, but when I remove the echo it works for me. if ! php -m | grep -q trader; then echo 'not existent'; fi
    – Jelmer
    May 21 at 12:29
  • @Jelmer Your code has very little in common with the code in the question, so you can't expect the answer's code to work as is, without editing.
    – they
    Nov 19 at 7:41
6

Since you're already using bash, you could keep it internal to bash:

if [[ $OUTPUT =~ (Status:[[:space:]]200) ]]; then
  echo match
fi

Sample runs:

OUTPUT='something bogus'
[[ $OUTPUT =~ (Status:[[:space:]]200) ]] && echo match


OUTPUT='something good (Status: 200)'
[[ $OUTPUT =~ (Status:[[:space:]]200) ]] && echo match
match
4

This is not an answer to your question, but few suggestions from a fellow scripter:

  • Use $() instead of backticks, don't use them both
  • Indent conditional if statements
  • Remove unnecessary usage of $()

Consistentecy and simple rules will help you debug and maintain scripts in a long run ...

#!/bin/bash

LOGIN="email"
TOKEN="token"
DOMAIN_ID="domain"
RECORD_ID="record"
IP=$(curl -s http://icanhazip.com/)

OUTPUT=$(
curl -H "Accept: application/json" \
    -H "Content-Type: application/json" \
    -H "X-DNSimple-Domain-Token: $TOKEN" \
    -X "PUT" \
    -i "https://api.dnsimple.com/v1/domains/$DOMAIN_ID/records/$RECORD_ID" \
    -d "{\"record\":{\"content\":\"$IP\"}}"
)

if ! echo "$OUTPUT" | grep -q "(Status:\s200)"; then
    echo "match"
    echo "$OUTPUT" | grep -oP '(?<="message":")(.[^"]*)' >> /home/ddns/ddns.log
    echo "$OUTPUT"| grep -P '(Status:\s[0-9]{3}\s)' >> /home/ddns/ddns.log
fi

Not the answer you're looking for? Browse other questions tagged or ask your own question.