web-dev-qa-db-fra.com

Stocker JSON directement dans le script bash avec des variables?

Je vais faire une préface en disant que "non, trouver une autre façon de procéder" est une réponse acceptable ici.

Existe-t-il un moyen fiable de stocker un petit morceau de JSON dans une variable bash à utiliser dans une commande AWS CLI exécutée à partir du même script?

Je vais exécuter un travail à partir de Jenkins qui met à jour un enregistrement AWS Route53, ce qui nécessite UPSERTing un fichier JSON avec la modification des enregistrements. Parce qu'il s'exécute à partir de Jenkins, il n'y a pas de stockage local où je peux conserver ce fichier, et j'aimerais vraiment éviter d'avoir à faire une vérification git à chaque fois que ce projet s'exécutera (qui sera une fois par heure).

Idéalement, le stockage des données dans une variable ($foo) Et leur appel dans le cadre de la commande change-resource-record-sets Serait plus pratique compte tenu de la configuration de Jenkins, mais je ne sais pas exactement comment citer/stocker JSON dans bash - peut-il être fait en toute sécurité?

Le JSON spécifique dans ce cas est le suivant;

{"Comment":"Update DNSName.","Changes":[{"Action":"UPSERT","ResourceRecordSet":{"Name":"alex.","Type":"A","AliasTarget":{"HostedZoneId":"######","DNSName":"$bar","EvaluateTargetHealth":false}}}]}

Comme complication supplémentaire, la valeur DNSName - $bar - doit être développée.

10
Alex

Vous pouvez utiliser un here-doc:

foo=$(cat <<EOF
{"Comment":"Update DNSName.","Changes":[{"Action":"UPSERT","ResourceRecordSet":{"Name":"alex.","Type":"A","AliasTarget":{"HostedZoneId":"######","DNSName":"$bar","EvaluateTargetHealth":false}}}]}
EOF
)

En laissant EOF dans la première ligne sans guillemets, le contenu de l'ici-doc sera soumis à l'expansion des paramètres, donc votre $bar s'étend à tout ce que vous y mettez.

Si vous pouvez avoir des sauts de ligne dans votre JSON, vous pouvez le rendre un peu plus lisible:

foo=$(cat <<EOF
{
  "Comment": "Update DNSName.",
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "alex.",
        "Type": "A",
        "AliasTarget": {
          "HostedZoneId": "######",
          "DNSName": "$bar",
          "EvaluateTargetHealth": false
        }
      }
    }
  ]
}
EOF
)

ou même (le premier retrait de chaque ligne doit être un onglet)

foo=$(cat <<-EOF
    {
      "Comment": "Update DNSName.",
      "Changes": [
        {
          "Action": "UPSERT",
          "ResourceRecordSet": {
            "Name": "alex.",
            "Type": "A",
            "AliasTarget": {
              "HostedZoneId": "######",
              "DNSName": "baz",
              "EvaluateTargetHealth": false
            }
          }
        }
      ]
    }
    EOF
)

et pour montrer comment cela est stocké, y compris les guillemets (en supposant que bar=baz):

$ declare -p foo
declare -- foo="{
  \"Comment\": \"Update DNSName.\",
  \"Changes\": [
    {
      \"Action\": \"UPSERT\",
      \"ResourceRecordSet\": {
        \"Name\": \"alex.\",
        \"Type\": \"A\",
        \"AliasTarget\": {
          \"HostedZoneId\": \"######\",
          \"DNSName\": \"baz\",
          \"EvaluateTargetHealth\": false
        }
      }
    }
  ]
}"

Étant donné que cela étend les métacaractères Shell, vous pouvez rencontrer des problèmes si votre JSON contient quelque chose comme *, vous pouvez donc affecter directement, mais faites attention à ne pas citer entre $bar:

foo='{"Comment":"Update DNSName.","Changes":[{"Action":"UPSERT","ResourceRecordSet":{"Name":"alex.","Type":"A","AliasTarget":{"HostedZoneId":"######","DNSName":"'"$bar"'","EvaluateTargetHealth":false}}}]}'

Notez la citation de $bar: c'est

"'"$bar"'"
│││    │││
│││    ││└ literal double quote
│││    │└ opening syntactical single quote
│││    └ closing syntactical double quote
││└ opening syntactical double quote
│└ closing syntactical single quote
└ literal double quote
33
Benjamin W.

Il peut être stocké en toute sécurité; générer c'est une autre affaire, car le contenu de $bar peut avoir besoin d'être encodé. Laissez un outil comme jq gérer la création du JSON.

var=$(jq -n --arg b "$bar" '{
  Comment: "Update DNSName.",
  Changes: [
    {
      Action: "UPSERT",
      ResourceRecordSet: {
        Name: "alex.",
        Type: "A",
        AliasTarget: {
          HostedZoneId: "######",
          DNSName: $b,
          EvaluateTargetHealth: false
        }
      }
    }
  ]
}')
9
chepner