0

I have a bootstrap script. After every time it runs, I want to keep track of its exit status in a JSON file. JSON file can have other fields too.

Case 1: The very first time it runs, JSON file will be created & a field node_bootstrap_status with boolean value will be added to it.

Case 2: In subsequent runs, JSON file will pre-exist. But in this case, I want to update same JSON field node_bootstrap_status with the outcome(again boolean).

I wrote the following bash script. It works for 1st case. In second case however, it ends up deleting everything in pre-existing JSON file.

exit_code=1

node_info_file="/etc/node_info.json"


if [[ -f $node_info_file ]]; then
  # /etc/node_info.json exists
  echo "${node_info_file} exists"
  if [ $exit_code = 0 ]; then
    cat $node_info_file | jq --argjson node_bootstrap_status true '{"node_bootstrap_status": $node_bootstrap_status}' > $node_info_file
  else
    cat $node_info_file | jq --argjson node_bootstrap_status false '{"node_bootstrap_status": $node_bootstrap_status}' > $node_info_file
  fi  
else
  # /etc/node_info.json does NOT exists
  echo "${node_info_file} does not exist"
  touch ${node_info_file}
  if [ $exit_code = 0 ]; then
    echo '{}' | jq --argjson node_bootstrap_status true '{"node_bootstrap_status": $node_bootstrap_status}' > $node_info_file
  else
    echo '{}' | jq --argjson node_bootstrap_status false '{"node_bootstrap_status": $node_bootstrap_status}' > $node_info_file
  fi  
fi

expected outcome:

cat /etc/node_info.json 
{
  "node_bootstrap_status": true/false,
  "foo": "bar"
}
Korba
  • 435
  • 1
  • 4
  • 18
  • Partially. It works if this is the only field in JSON file. If there are more fields, it cries ```parse error: Expected another key-value pair at line 4, column 1``` – Korba Feb 11 '23 at 03:25
  • 1
    Does this answer your question? [Transfer or merge only some properties from one JSON file to another with jq](https://stackoverflow.com/questions/75391973/transfer-or-merge-only-some-properties-from-one-json-file-to-another-with-jq) – knittl Feb 11 '23 at 08:33
  • You cannot read and write from the same file in a single command. You have to write and then move a temporary file or use GNU `sponge`. For updating/merging the file, the marked duplicate could help or give useful pointers. https://stackoverflow.com/questions/75391973/transfer-or-merge-only-some-properties-from-one-json-file-to-another-with-jq/75391974#75391974 – knittl Feb 11 '23 at 08:34

2 Answers2

2

You're off to a good start - but you'd want to use assignment rather than the sort of { ... } syntax like so:

node_info_file="node_info.json"

set_status() {
    local value="$1"

    mv -f "$node_info_file" "$node_info_file.tmp"

    # Set property key with: '.node_bootstrap_status = ...'
    jq --argjson node_bootstrap_status "$value" '.node_bootstrap_status = $node_bootstrap_status' "$node_info_file.tmp" > "$node_info_file"

    rm -f "$node_info_file.tmp"
}

# if node_info.json does NOT exists; create it
if [ ! -f $node_info_file ]; then
    printf '%s\n' '{}' > "$node_info_file"
fi

set_status true
set_status false

I tested this with empty JSON, and with other contents, and it worked as expected.

Also, make sure you quote "$node_info_file" - it's good practice. If you use ShellCheck then it'll catch those types of errors for you.

hyperupcall
  • 869
  • 10
  • 21
0

Try to adapt this version to your needs :

#!/usr/bin/env bash

exit_code=1
node_info_file="/etc/node_info.json"

test -f "$node_info_file" || echo {} > "$node_info_file"
[ $exit_code = 0 ] && status=true || status=false
tmp=$(mktemp)
jq --argjson node_bootstrap_status $status '{$node_bootstrap_status}' "$node_info_file" > $tmp
mv $tmp "$node_info_file"

Just a side note, it may not be a good idea to save node_info.json in /etc.

Philippe
  • 20,025
  • 2
  • 23
  • 32