10

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?

  • 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. – CircularRecursion 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. – CircularRecursion Apr 12 '16 at 8:29
14

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.

3

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
3

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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