Використання curl POST зі змінними, визначеними у функціях скрипту bash


176

Коли я лунаю, я отримую це, що запускається, коли я ввожу його в термінал

curl -i \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X POST --data '{"account":{"email":"akdgdtk@test.com","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

Але при запуску у файлі скриптів bash я отримую цю помилку

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

це код у файлі

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:xxxxx@xxxx-www.xxxxx.com/xxxxx/xxxx/xxxx"

Я припускаю, що у моїх лапок є проблема, але я багато грав з ними, і я помилявся. Усі змінні визначаються різними функціями у фактичному сценарії

Відповіді:


274

Вам не потрібно передавати лапки, що додають власні заголовки до згортання. Також dataслід вказати ваші змінні в середині аргументу.

Спочатку напишіть функцію, яка генерує дані про пост вашого сценарію. Це позбавляє вас від різного роду головних болів, що стосуються котирування оболонки, і полегшує зчитування сценарію підтримки, ніж подавання даних про публікацію в рядку виклику curl, як у вашій спробі:

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
}

Тоді легко використовувати цю функцію у виклику curl:

curl -i \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X POST --data "$(generate_post_data)" "https://xxx:xxxxx@xxxx-www.xxxxx.com/xxxxx/xxxx/xxxx"

Це означає, що ось декілька роз'яснень щодо правил котирування оболонки:

Подвійні лапки в -Hаргументах (як і в -H "foo bar") кажуть bash зберігати те, що знаходиться всередині, як єдиний аргумент (навіть якщо він містить пробіли).

Одиничні лапки в --dataаргументі (як і в --data 'foo bar') роблять те ж саме, за винятком того, що вони передають усний текст дослівно (включаючи символи подвійної цитати та знак долара).

Щоб вставити змінну в середині одного цитованого тексту, ви повинні закінчити апостроф, потім зчепити з цитованого змінної подвійний, і повторно відкрити єдину цитату , щоб продовжити текст: 'foo bar'"$variable"'more foo'.


9
"'" $ <ім'я змінної> "'" вирішив мою проблему, коли мені потрібно було не пропустити цитати. Дякую.
Усман

1
Це рішення працює, але я думаю, ви можете випускати додаткові подвійні лапки навколо змінної. Тож замість цього: --data '{"account": {"email": "'" $ email "'"}}' ви можете це зробити: --data '{"account": {"email": " '$ email' "}} '
кручений потік

3
Не працював , коли був пробіл після другого EOF: EOF . Після його зняття все добре.
Клаас

2
@dbreaux Це залежить від місця запуску команди curl. Якщо команда знаходиться в сценарії, ви просто визначте функцію в будь-якому місці над цим сценарієм. Якщо ви запускаєте curl безпосередньо з командного рядка, у вас є кілька варіантів, один з яких - ввести функцію в новий файл, а потім у командному рядку запустити source my_new_fileдля визначення функції у вашому поточному середовищі. Після цього можна виконати команду curl, як зазначено.
Сер Афон

2
@slashdottir Це баш-функція під назвою Here Documents. Ви можете прочитати про це більш докладно за цим посиланням - зокрема, ознайомтеся з Прикладом 19-5. Тут також вже є повне запитання про це на SO.
Сер Афон

103

Тестування рішення за допомогою https://httpbin.org/ та вбудованого скрипту bash
1. Для змінних без пробілів у ньому, тобто 1:
Просто додайте 'до та після $variableзаміни потрібного рядка

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

2. Для введення з пробілами:
Оберніть змінну додатковими, "тобто "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

Нічого не працює :)


1
Не працює, коли $iмістить пробіли. :(
Василь Боровяк

Чи можете ви розмістити приклад?
pbaranski

1
Звичайно. i="a b"замість for-loop
Василь Боровяк

5
Я виявив, що прийнята та друга проголосована відповідь не працює /bin/sh. Однак ця відповідь зробила трюк. І це набагато простіше, ніж інші відповіді. Дуже дякую! Я відредагував вашу відповідь за допомогою кращого формату для обгортання рядків Інакше блиск складно помітити.
Народний

1
Велике спасибі @pbaranski, ви зекономили багато мого часу
sudhir tataraju

32

Curl може розміщувати бінарні дані з файлу, тому я використовував підстановку процесу та використовував дескриптори файлів, коли мені потрібно опублікувати щось неприємне з curl і все ще хочу отримати доступ до vars у поточній оболонці. Щось на зразок:

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

Це закінчується виглядом, --data @/dev/fd/<some number>який просто обробляється як звичайний файл. У будь-якому випадку, якщо ви хочете, щоб він працював локально, просто запустіть nc -l 8080перший і в іншому снаряді обстріляйте вищезгадану команду. Ви побачите щось на кшталт:

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  }

Як ви бачите, ви можете зателефонувати в допоміжні оболонки та інше, а також довідкові параметри в гередоці. Щасливий злом надії це допомагає '"'"'""""'''""''.


2
Інша відповідь не спрацювала для мене, оскільки я намагався викликати її в попередженні від Zabbix. Цей вирішує його ідеально і є більш чистим.
0rkan

Але що робити, якщо ви введете код у функцію bash: myFunction () {....}?
Ганиновський

1
Варто зазначити, що цей рецепт працює лише в тому випадку, якщо сценарій скопійовано дослівно (тобто немає переформатування EOF, дужки тощо)
Vader B

9

Пізніше на кілька років, але це може допомогти комусь, якщо ви використовуєте заміну eval або backtick:

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

Використання sed для зняття лапок початку та кінця відповіді

$(curl --silent -H "Content-Type: application/json" https://${target_host}/runs/get-work -d ${postDataJson} | sed -e 's/^"//' -e 's/"$//')

4
  • інформація від сер Афон працювала чудово !!

Ось як мені довелося використовувати його в моєму скрипті curl для couchDB. Це дійсно багато допомогло. Дякую!

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

4

Ось що насправді працювало для мене, після вказівки з відповідей тут:

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'

2

Існуючі відповіді вказують, що curl може розміщувати дані з файлу та використовувати гередоки, щоб уникнути зайвої цитати та чітко розбити JSON на нові рядки. Однак не потрібно визначати функцію або захоплювати вихід з кота, оскільки curl може розміщувати дані зі стандартного введення. Я вважаю цю форму дуже читаною:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.