2

In the bash script below, I have JSON object and need to have key hostname with random name, like host-$NAME (i.e. host-1, host-3). How to do it ?

#!/bin/bash
NAME=($(( ( RANDOM % 10 )  + 1 )))
OUTPUT='{
  "hostname": "host-$NAME",
  "plan": "baremetal_0",               
  "operating_system": "coreos_stable"
}'

echo $OUTPUT

The script output is below

$ ./packet-ask.sh 
{ "hostname": "host-$NAME", "plan": "baremetal_0", "operating_system": "coreos_stable" }
chicks
  • 1,112
  • 1
  • 9
  • 27
irom
  • 453
  • 2
  • 10
  • 20

2 Answers2

3

Try this:

OUTPUT='{
  "hostname": "host-'$NAME'",
...
Guido
  • 4,014
  • 13
  • 22
  • In general, this is a rally bad suggestion as `$NAME` may contain characters that needs to be encoded before included in the JSON document. Also, this solution solves the issue by leaving the `$NAME` expansion totally unquoted, which is generally a bad idea. – Kusalananda Jul 10 '21 at 22:01
  • @Kusalananda As seen in line 2 of the script, `$NAME` is only going to contain digits. – Guido Jul 12 '21 at 00:16
  • Is there any _harm_ in doing it correctly? You are actually leaving an expansion of a shell variable totally unquoted even though it would be _easy_ to remedy this. See e.g. [Security implications of forgetting to quote a variable in bash/POSIX shells](https://unix.stackexchange.com/a/171347) – Kusalananda Jul 12 '21 at 05:36
0

The issue is that the shell does not expand variables inside single-quoted strings. A minor other thing is that your NAME variable actually happens to be an array due to the way you assign the value to it (NAME=(...)). You also use your OUTPUT variable unquoted (which would split its contents on white-spaces and apply filename globbing to all the generated words) and with echo (which may, under some circumstances, modify the data that it's outputting).

Consider adopting safer ways of creating JSON documents. It is not always possible to inject a shell string into a JSON document. In this particular case, it ought to be fairly safe, but you generally want to use a tool that knows how to handle characters like quotes and newlines properly.

Using jo to create the JSON document:

#!/bin/bash

printf -v name 'host-%s' "$(( 1 + (RANDOM % 10) ))"

jo hostname="$name" plan='baremetal_0' operating_system='coreos_stable'

Using jq to do the same thing:

#!/bin/bash

printf -v name 'host-%s' "$(( 1 + (RANDOM % 10) ))"

jq -n -c --arg name "$name" \
    '{ "hostname": $name, "plan": "baremetal_0", "operating_system": "coeros_stable" }'

Note that in both these cases,

  1. The string $name is properly JSON encoded. This matters since it's possible that one at some later point decides that $name should be some other random string that may need encoding.
  2. The output from jo/jq is not saved in a shell variable. This is not needed since we're just interested in outputting the generated JSON document.
Kusalananda
  • 320,670
  • 36
  • 633
  • 936