Verwenden von Curl-POST mit Variablen, die in Bash-Skriptfunktionen definiert sind

175

Wenn ich ein Echo erhalte, erhalte ich dieses, das ausgeführt wird, wenn ich es in das Terminal eingebe

curl -i \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X POST --data '{"account":{"email":"[email protected]","screenName":"akdgdtk","type":"NIKE","passwordSettings":{"password":"Starwars1","passwordConfirm":"Starwars1"}},"firstName":"Test","lastName":"User","middleName":"ObiWan","locale":"en_US","registrationSiteId":"520","receiveEmail":"false","dateOfBirth":"1984-12-25","mobileNumber":"9175555555","gender":"male","fuelActivationDate":"2010-10-22","postalCode":"10022","country":"US","city":"Beverton","state":"OR","bio":"This is a test user","jpFirstNameKana":"unsure","jpLastNameKana":"ofthis","height":"80","weight":"175","distanceUnit":"MILES","weightUnit":"POUNDS","heightUnit":"FT/INCHES"}' https://xxx:xxxxx@xxxx-www.xxxxx.com/xxxxx/xxxx/xxxx

Aber wenn ich in der Bash-Skriptdatei ausgeführt werde, erhalte ich diesen Fehler

curl: (6) Could not resolve host: application; nodename nor servname provided, or not known
curl: (6) Could not resolve host: is; nodename nor servname provided, or not known
curl: (6) Could not resolve host: a; nodename nor servname provided, or not known
curl: (6) Could not resolve host: test; nodename nor servname provided, or not known
curl: (3) [globbing] unmatched close brace/bracket at pos 158

Dies ist der Code in der Datei

curl -i \
-H '"'Accept: application/json'"' \
-H '"'Content-Type:application/json'"' \
-X POST --data "'"'{"account":{"email":"'$email'","screenName":"'$screenName'","type":"'$theType'","passwordSettings":{"password":"'$password'","passwordConfirm":"'$password'"}},"firstName":"'$firstName'","lastName":"'$lastName'","middleName":"'$middleName'","locale":"'$locale'","registrationSiteId":"'$registrationSiteId'","receiveEmail":"'$receiveEmail'","dateOfBirth":"'$dob'","mobileNumber":"'$mobileNumber'","gender":"'$gender'","fuelActivationDate":"'$fuelActivationDate'","postalCode":"'$postalCode'","country":"'$country'","city":"'$city'","state":"'$state'","bio":"'$bio'","jpFirstNameKana":"'$jpFirstNameKana'","jpLastNameKana":"'$jpLastNameKana'","height":"'$height'","weight":"'$weight'","distanceUnit":"MILES","weightUnit":"POUNDS","heightUnit":"FT/INCHES"}'"'" "https://xxx:[email protected]/xxxxx/xxxx/xxxx"

Ich gehe davon aus, dass es ein Problem mit meinen Anführungszeichen gibt, aber ich habe viel mit ihnen gespielt und ähnliche Fehler erhalten. Alle Variablen werden im eigentlichen Skript mit unterschiedlichen Funktionen definiert

AGleasonTU
quelle

Antworten:

273

Sie müssen die Anführungszeichen, die die benutzerdefinierten Überschriften enthalten, nicht zum Einrollen übergeben. Außerdem sollten Ihre Variablen in der Mitte des dataArguments in Anführungszeichen gesetzt werden.

Schreiben Sie zunächst eine Funktion, die die Post-Daten Ihres Skripts generiert. Dies erspart Ihnen alle Arten von Kopfschmerzen beim Shell-Zitieren und erleichtert das Lesen und Verwalten des Skripts, als die Post-Daten wie bei Ihrem Versuch in die Aufrufzeile von curl einzugeben:

generate_post_data()
{
  cat <<EOF
{
  "account": {
    "email": "$email",
    "screenName": "$screenName",
    "type": "$theType",
    "passwordSettings": {
      "password": "$password",
      "passwordConfirm": "$password"
    }
  },
  "firstName": "$firstName",
  "lastName": "$lastName",
  "middleName": "$middleName",
  "locale": "$locale",
  "registrationSiteId": "$registrationSiteId",
  "receiveEmail": "$receiveEmail",
  "dateOfBirth": "$dob",
  "mobileNumber": "$mobileNumber",
  "gender": "$gender",
  "fuelActivationDate": "$fuelActivationDate",
  "postalCode": "$postalCode",
  "country": "$country",
  "city": "$city",
  "state": "$state",
  "bio": "$bio",
  "jpFirstNameKana": "$jpFirstNameKana",
  "jpLastNameKana": "$jpLastNameKana",
  "height": "$height",
  "weight": "$weight",
  "distanceUnit": "MILES",
  "weightUnit": "POUNDS",
  "heightUnit": "FT/INCHES"
}
EOF
}

Es ist dann einfach, diese Funktion beim Aufrufen von Curl zu verwenden:

curl -i \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X POST --data "$(generate_post_data)" "https://xxx:[email protected]/xxxxx/xxxx/xxxx"

Hier einige Erläuterungen zu den Regeln für Shell-Zitate:

Die doppelten Anführungszeichen in den -HArgumenten (wie in -H "foo bar") weisen bash an, das Innere als einzelnes Argument beizubehalten (auch wenn es Leerzeichen enthält).

Die einfachen Anführungszeichen im --dataArgument (wie in --data 'foo bar') machen dasselbe, außer dass sie den gesamten Text wörtlich übergeben (einschließlich doppelter Anführungszeichen und des Dollarzeichens).

Um eine Variable in die Mitte eines Textes in einfachen Anführungszeichen einzufügen, müssen Sie das einfache Anführungszeichen beenden, dann mit der Variablen in doppelten Anführungszeichen verketten und das einfache Anführungszeichen erneut öffnen, um den Text fortzusetzen : 'foo bar'"$variable"'more foo'.

Sir Athos
quelle
9
"'" $ <Variablenname> "'" löste mein Problem, bei dem Anführungszeichen nicht weggelassen werden mussten. Vielen Dank.
Usman
1
Diese Lösung funktioniert, aber ich denke, Sie können die zusätzlichen doppelten Anführungszeichen um die Variable ausgeben. Anstelle von :data '{"account": {"email": "'" $ email "'"}}' können Sie dies tun: --data '{"account": {"email": " '$ email' "}} '
Twistedstream
3
Hat nicht funktioniert, als nach dem zweiten EOF ein Leerzeichen vorhanden war : EOF . Nach dem Entfernen ist alles in Ordnung.
Klaas
2
@dbreaux Das hängt davon ab, wo Sie den Befehl curl ausführen. Wenn sich der Befehl in einem Skript befindet, definieren Sie die Funktion einfach irgendwo darüber im selben Skript. Wenn Sie curl direkt über die Befehlszeile ausführen, haben Sie mehrere Möglichkeiten. Eine davon besteht darin, die Funktion in eine neue Datei einzugeben und dann in der Befehlszeile auszuführen source my_new_file, um die Funktion in Ihrer aktuellen Umgebung zu definieren. Danach können Sie den Befehl curl wie angegeben ausführen.
Sir Athos
2
@slashdottir Das ist eine Bash-Funktion namens Here Documents. Weitere Informationen hierzu finden Sie unter diesem Link. Lesen Sie insbesondere Beispiel 19-5. Es gibt auch schon eine vollständige Frage dazu hier auf SO.
Sir Athos
103

Lösung getestet mit https://httpbin.org/ und Inline-Bash-Skript
1. Für Variablen ohne Leerzeichen, dh 1:
Fügen Sie einfach 'vor und nach $variabledem Ersetzen der gewünschten Zeichenfolge hinzu

for i in {1..3}; do \
  curl -X POST -H "Content-Type: application/json" -d \
    '{"number":"'$i'"}' "https://httpbin.org/post"; \
done

2. Für die Eingabe mit Leerzeichen:
Wrap-Variable mit zusätzlichen "dh "el a":

declare -a arr=("el a" "el b" "el c"); for i in "${arr[@]}"; do \
  curl -X POST -H "Content-Type: application/json" -d \
    '{"elem":"'"$i"'"}' "https://httpbin.org/post"; \
done

Wow funktioniert :)

pbaranski
quelle
1
Funktioniert nicht, wenn wann $iLeerzeichen enthalten sind. :(
Vasyl Boroviak
Können Sie ein Beispiel posten?
Pbaranski
1
Sicher. i="a b"statt for-Schleife
Vasyl Boroviak
5
Ich habe festgestellt, dass die akzeptierte und die zweitstimmige Antwort nicht funktionieren /bin/sh. Diese Antwort hat jedoch den Trick getan. Und es ist viel einfacher als die anderen Antworten. Ich danke dir sehr! Ich habe Ihre Antwort mit einer schöneren Formatierung für Zeilenumbrüche bearbeitet. Ansonsten ist die Brillanz schwer zu erkennen. Prost Kumpel
Vasyl Boroviak
1
Vielen Dank @pbaranski Sie haben viel Zeit
gespart
32

Curl kann Binärdaten aus einer Datei veröffentlichen, daher habe ich die Prozessersetzung verwendet und Dateideskriptoren verwendet, wenn ich etwas Böses mit Curl veröffentlichen muss und trotzdem Zugriff auf die Variablen in der aktuellen Shell haben möchte. Etwas wie:

curl "http://localhost:8080" \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
--data @<(cat <<EOF
{
  "me": "$USER",
  "something": $(date +%s)
  }
EOF
)

Dies sieht --data @/dev/fd/<some number>so aus, als würde es wie eine normale Datei verarbeitet. Wie auch immer, wenn Sie möchten, dass es lokal funktioniert, führen Sie es nc -l 8080zuerst aus und feuern Sie den obigen Befehl in einer anderen Shell ab. Sie werden so etwas sehen wie:

POST / HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.43.0
Accept: application/json
Content-Type:application/json
Content-Length: 43

{  "me": "username",  "something": 1465057519  }

Wie Sie sehen können, können Sie im Heredoc Subshells und so weiter sowie Referenz-Vars aufrufen. Happy Hacking hoffe das hilft bei der '"'"'""""'''""''.

Che Ruisi-Besares
quelle
2
Die andere Antwort hat bei mir nicht funktioniert, da ich versucht habe, sie in einer Warnung von Zabbix aufzurufen. Dieser löst es perfekt und ist sauberer.
0rkan
Aber was ist, wenn Sie den Code in eine Bash-Funktion einfügen: myFunction () {....}?
Hanynowsky
1
Es ist erwähnenswert, dass dieses Rezept nur funktioniert, wenn das Skript wörtlich kopiert wird (dh keine Neuformatierung von EOF, geschweiften Klammern usw.)
Vader B
9

Ein paar Jahre zu spät, aber dies könnte jemandem helfen, wenn Sie eine Eval- oder Backtick-Substitution verwenden:

postDataJson="{\"guid\":\"$guid\",\"auth_token\":\"$token\"}"

Verwenden von sed, um Anführungszeichen vom Anfang und Ende der Antwort zu entfernen

$(curl --silent -H "Content-Type: application/json" https://${target_host}/runs/get-work -d ${postDataJson} | sed -e 's/^"//' -e 's/"$//')
Glyphe
quelle
4
  • Die Infos von Sir Athos haben perfekt funktioniert !!

Hier ist, wie ich es in meinem Curl-Skript für couchDB verwenden musste. Es hat wirklich sehr geholfen. Vielen Dank!

bin/curl -X PUT "db_domain_name_:5984/_config/vhosts/$1.couchdb" -d '"/'"$1"'/"' --user "admin:*****"
thargenediad
quelle
3

Folgendes hat bei mir tatsächlich funktioniert, nachdem ich die Antworten hier erhalten habe:

export BASH_VARIABLE="[1,2,3]"
curl http://localhost:8080/path -d "$(cat <<EOF
{
  "name": $BASH_VARIABLE,
  "something": [
    "value1",
    "value2",
    "value3"
  ]
}
EOF
)" -H 'Content-Type: application/json'
xgMz
quelle
2

Bestehende Antworten weisen darauf hin, dass Curl Daten aus einer Datei veröffentlichen und Heredocs einsetzen kann, um zu verhindern, dass übermäßiges Zitat entweicht, und den JSON eindeutig in neue Zeilen aufzuteilen. Es ist jedoch nicht erforderlich, eine Funktion zu definieren oder die Ausgabe von cat zu erfassen, da Curl Daten von der Standardeingabe veröffentlichen kann. Ich finde dieses Formular sehr lesbar:

curl -X POST -H 'Content-Type:application/json' --data '$@-' ${API_URL} << EOF
{
  "account": {
    "email": "$email",
    "screenName": "$screenName",
    "type": "$theType",
    "passwordSettings": {
      "password": "$password",
      "passwordConfirm": "$password"
    }
  },
  "firstName": "$firstName",
  "lastName": "$lastName",
  "middleName": "$middleName",
  "locale": "$locale",
  "registrationSiteId": "$registrationSiteId",
  "receiveEmail": "$receiveEmail",
  "dateOfBirth": "$dob",
  "mobileNumber": "$mobileNumber",
  "gender": "$gender",
  "fuelActivationDate": "$fuelActivationDate",
  "postalCode": "$postalCode",
  "country": "$country",
  "city": "$city",
  "state": "$state",
  "bio": "$bio",
  "jpFirstNameKana": "$jpFirstNameKana",
  "jpLastNameKana": "$jpLastNameKana",
  "height": "$height",
  "weight": "$weight",
  "distanceUnit": "MILES",
  "weightUnit": "POUNDS",
  "heightUnit": "FT/INCHES"
}
EOF
abyrd
quelle