1

I am trying to update a couple values in a json array (separate file) with a shell script. Basically the logic is, set an environment variable called URL, ping that URL and add it to the json-- if 0, update another json field to SUCCESS, else update to FAILED.

Here is are the files:

info.json:

{
 "name": "PingTest",",
 "metrics": [
{
  "event_type": "PingResult",
  "provider": "test",
  "providerUrl": "URL",
  "providerResult": "RESULT"
}
]
}

pinger.sh:

#!/bin/sh

JSON=`cat info.json` #read in JSON

#Assume URL variable is set to www.dksmfdkf.com 
ping -q -c 1 "$URL" > /dev/null #ping url
if [ $? -eq 0 ]; then #if ping success, replace result in json template
  JSON=`echo ${JSON} | jq --arg v "$URL" '.metrics[].providerUrl |= $v' 
  info.json`
  JSON=`echo ${JSON} | jq '.metrics[].providerResult |= "SUCCESS"' info.json`
else
  JSON=`echo ${JSON} | jq --arg v "$URL" '.metrics[].providerUrl |= $v' 
  info.json`
  JSON=`echo ${JSON} | jq '.metrics[].providerResult |= "FAILED"' info.json`
fi

#Remove whitespace from json
JSON=`echo $JSON | tr -d ' \t\n\r\f'`

#Print the result
echo "$JSON"

The problem is my json file isn't getting updated properly, example result when running:

home:InfraPingExtension home$ ./pinger.sh
ping: cannot resolve : Unknown host
{
  "name": "PingTest",
  "metrics": [
  {
    "event_type": "PingResult",
    "provider": "test",
    "providerUrl": "",
    "providerResult": "RESULT"
  }
 ]
 }
{
  "name": "PingTest",
  "metrics": [
{
  "event_type": "PingResult",
  "provider": "test",
  "providerUrl": "URL",
  "providerResult": "FAILED"
}
  ]
}

{"name":"PingTest","metrics":[{"event_type":"PingResult","provider":"test","providerUrl":"URL","providerResult":"RESULT"}]}
5
  • 1
    FYI -- all-caps variable names are used for variables with meaning to the shell or OS; all other names are reserved for application usage (so your own variables should have at least one lowercase letter so they can't conflict with names reserved by future versions of the shell). See pubs.opengroup.org/onlinepubs/9699919799/basedefs/…, fourth paragraph. Commented Jan 29, 2018 at 16:09
  • 1
    And btw, if you don't want semantically-irrelevant whitespace in your JSON, use the -c argument to jq; that way you don't corrupt your data (if there are actually spaces within it). Commented Jan 29, 2018 at 16:09
  • 1
    Most importantly, right now, your $? doesn't refer to the success of ping but refers instead to the success of the jq you're running after the ping. This is part of why instead of running ping and then testing $?, it's better practice to directly write if ping -c 1 "$host"; then -- there's no way your result can be something other than what you meant to test. Commented Jan 29, 2018 at 16:11
  • Possible duplicate of Jq to replace text directly on file (like sed -i) Commented Jan 29, 2018 at 16:32
  • BTW, I'd strongly suggest having a single JSON template that doesn't change you use as your input file, rather than re-processing the same file over-and-over; output is more predictable if input is fixed, as otherwise you can get into a state where one transient failure corrupts the file causing all future runs to fail. Commented Jan 29, 2018 at 17:16

1 Answer 1

3

This would be greatly simplified by only calling jq once.

host=${URL#http://}; host=${host#https://}; host=${host%%/*}
if ping -q -c 1 "$host"; then
  result=SUCCESS
else
  result=FAILED
fi

JSON=$(
  jq -c \
     --arg url "$URL" \
     --arg result "$result" \
     '.metrics[].providerUrl |= $url
      | .metrics[].providerResult |= $result
  ' info.json
)
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! This is a more robust solution

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.