0

Hello Stackoverflow community

If i run this shell script i want it to simply add a entry into my elasticsearch index backup_timestamps.

In the field "timestamp" should be the current time varible. And in the field "system_name" should be the current hostname variable of the machine.

#!/bin/sh

timestamp=`date +"%Y-%m-%d %T"`
system_name=`hostname`


sudo curl -u elastic:PASSWORD -XPOST "https://localhost:9200/backup_timestamps/_doc" --cacert ./certs/ca/ca.crt -H 'Content-Type: application/json' -d '
{
    "timestamp": "$timestamp",
    "system_name": "$system_name"
}'

echo "("$timestamp" , "$system_name")"

After running this shell script what i get in the elasticsearch db is this:

{
    "_index" : "backup_timestamps",
    "_id" : "BybOdYABhPvBW1kMbwKh",
    "_score" : 1.0,
    "_source" : {
    "timestamp" : "$timestamp",
    "system_name" : "$system_name"
}

But what i want to get is this:

{
    "_index" : "backup_timestamps",
    "_id" : "BybOdYABhPvBW1kMbwKh",
    "_score" : 1.0,
    "_source" : {
    "timestamp" : "2022-01-01 12:00:00",
    "system_name" : "my-server-or-whatever"
}

edit1:

The answer was this:

sudo curl \
    -u elastic:PASSWORD -XPOST \
    "https://localhost:9200/backup_timestamps/_doc" \
    --cacert ./certs/ca/ca.crt \
    -H 'Content-Type: application/json' \
    -d "{\"timestamp\":\"$timestamp\",\"system_name\": \"$system_name\"}"
Issykul
  • 23
  • 5
  • Don't tag bash if you're actually using `/bin/sh`. `sh` is not bash. Start your script with `#!/usr/bin/env bash` if you want bash-only features to be available during execution. – Charles Duffy Apr 29 '22 at 15:20

2 Answers2

2

Another way to do it without messing with escaped quotes, but only for simple string values like in your example (i.e. non-JSON string, string with literal quotes, newlines, tabs, etc):

PAYLOAD_TEMPL='{
    "timestamp": "%s",
    "system_name": "%s"
}'

PAYLOAD=$(printf "${PAYLOAD_TEMPL}" "${timestamp}" "${system_name}")

sudo curl -u elastic:PASSWORD -XPOST "https://localhost:9200/backup_timestamps/_doc" --cacert ./certs/ca/ca.crt -H 'Content-Type: application/json' -d "$PAYLOAD"
Val
  • 207,596
  • 13
  • 358
  • 360
  • How would i use this in my curl statement? – Issykul Apr 29 '22 at 15:14
  • See my updated answer – Val Apr 29 '22 at 15:14
  • This doesn't work if your values need to be escaped to be valid JSON. It's much better practice to use `jq` or another syntax-aware tool. – Charles Duffy Apr 29 '22 at 15:20
  • @CharlesDuffy it's not the case here – Val Apr 29 '22 at 15:21
  • @Val, ...with the values the OP has right now, but we aren't telling them "this is how you do X with these specific values", but "this is how you do X". A general answer should either be general, or should come with explicit caveats describing its limits. – Charles Duffy Apr 29 '22 at 15:21
  • @CharlesDuffy yes, if you're over-engineering it, you're right. I've updated my answer accordingly – Val Apr 29 '22 at 15:22
0

You have your JSON packet inside single quotes.

Single quotes don't allow variable substitution, double quotes do:

$ THING=hello
$ echo "$THING"
hello
$ echo '$THING'
$THING

Put your packet in double quotes, which would look something like this:

sudo curl \
    -u elastic:PASSWORD -XPOST \
    "https://localhost:9200/backup_timestamps/_doc" \
    --cacert ./certs/ca/ca.crt \
    -H 'Content-Type: application/json' \
    -d "{\"timestamp\":\"$timestamp\",\"system_name\": \"$system_name\"}"
Inigo Selwood
  • 822
  • 9
  • 20
  • Why do you use the \ in before every " ? – Issykul Apr 29 '22 at 15:12
  • The backslash escapes the quote mark. Without them, the string would start/end with every new double-quote – Inigo Selwood Apr 29 '22 at 15:14
  • As with the other answer, this doesn't work properly with all possible strings -- strings with literal quotes, tab characters, newlines, and other characters won't work. See the linked duplicate's answers using `jq` for a more general solution. – Charles Duffy Apr 29 '22 at 15:24