Curl POST işlevini bash komut dosyası işlevlerinde tanımlanan değişkenlerle kullanma


176

Yankı aldığımda, bunu terminale girdiğimde çalışıyorum

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

Ama bash komut dosyasında çalıştırıldığında, bu hatayı alıyorum

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

bu dosyadaki kod

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"

Tırnak işaretlerimle ilgili bir sorun olduğunu varsayıyorum, ancak onlarla çok oynadım ve benzer hatalar aldım. Tüm değişkenler gerçek komut dosyasında farklı işlevlerle tanımlanır

Yanıtlar:


274

Kıvrılmak için özel başlıkları içeren tırnak işaretlerini iletmeniz gerekmez. Ayrıca, dataargümanın ortasındaki değişkenleriniz alıntılanmalıdır.

İlk olarak, komut dosyanızın gönderi verilerini üreten bir işlev yazın. Bu sizi kabuk alıntılama ile ilgili her türlü baş ağrısından kurtarır ve betiğin okunmasını, denemenizdeki gibi kıvrımın çağrı hattındaki posta verilerini beslemekten daha kolay hale getirir:

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
}

Daha sonra bu işlevi kıvrılma çağrısında kullanmak kolaydır:

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"

Bu, kabuk alıntı kuralları hakkında birkaç açıklama aşağıdadır:

Bağımsız -Hdeğişkenlerdeki çift ​​tırnak (olduğu gibi -H "foo bar") bash'a içeride ne olduğunu tek bir bağımsız değişken olarak tutmasını söyler (boşluklar olsa bile).

Bağımsız --datadeğişkenteki tek tırnak işaretleri (olduğu gibi --data 'foo bar'), tüm metin kelimelerini (çift tırnak işareti ve dolar işareti dahil) geçmeleri dışında aynı şeyi yapar.

Tek bir alıntı metnin ortasında bir değişken eklemek için, daha sonra çift tırnaklı değişkenle bitiştirmek ve metni devam etmek tek alıntı yeniden açmak, tek alıntı sonlandırmak zorunda: 'foo bar'"$variable"'more foo'.


9
"'" $ <değişken adı> "'" tırnak işaretlerinin atlanmaması gerektiğinde sorunumu çözdü. Teşekkürler.
Usman

1
Bu çözüm işe yarıyor ama bence değişkeni çevreleyen ekstra çift tırnak işaretleri yayabilirsiniz. Bunun yerine: --data '{"account": {"email": "'" $ email "'"}}' bunu yapabilirsiniz: --data '{"account": {"email": " '$ email' "}} '
twistedstream

3
İkinci EOF sonra boşluk varken işe yaramadı: EOF . Çıkardıktan sonra her şey yolunda.
Klaas

2
@dbreaux Bu, curl komutunu çalıştırdığınız yere bağlıdır. Komut bir komut dosyasındaysa, işlevi aynı komut dosyasında üzerinde herhangi bir yerde tanımlarsınız. Curl komutunu doğrudan komut satırından çalıştırıyorsanız, bunlardan biri işlevi yeni bir dosyaya yazmak ve sonra komut satırında source my_new_filegeçerli ortamınızdaki işlevi tanımlamak için çalıştırılacak birkaç seçeneğiniz vardır. Bundan sonra curl komutunu belirtildiği gibi çalıştırabilirsiniz.
Sir Athos

2
@slashdottir Bu, Here Documents adlı bir bash özelliğidir. Bu bağlantıda daha ayrıntılı olarak okuyabilirsiniz - özellikle Örnek 19-5'e bakın. Ayrıca burada SO hakkında tam bir soru var .
Sir Athos

103

Https://httpbin.org/ ve satır içi bash betiği ile test edilen çözüm
1. İçinde boşluk olmayan değişkenler için yani 1: İstediğiniz dizeyi değiştirirken önce ve sonra
ekleyin'$variable

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

2. Boşluklu girişler için:
Değişkeni ek olarak "kaydırın "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

Vay canına :)


1
$iBoşluk olduğunda ne zaman işe yaramaz . :(
Vasyl Boroviak

Bir örnek gönderebilir misiniz?
pbaranski

1
Elbette. i="a b"for-loop yerine
Vasyl Boroviak

5
Kabul edilen ve ikinci oylanan cevabın işe yaramadığını buldum /bin/sh. Ancak, bu cevap hile yaptı. Ve diğer cevaplardan çok daha basit. Çok teşekkür ederim! Cevabınızı daha hoş satır kaydırma biçimlendirmesiyle düzenledim. Aksi takdirde, parlaklığı tespit etmek zordur. Şerefe dostum
Vasyl Boroviak

1
Teşekkürler çok @pbaranski çok zamanımı kurtardın
sudhir tataraju

32

Kıvırmak ile kötü bir şey göndermek ve hala geçerli kabuk vars erişim istiyorum her zaman işlem ikame kullanarak ve dosya tanımlayıcıları yararlanmak bu yüzden kıvırmak bir dosyadan ikili veri gönderebilirsiniz. Gibi bir şey:

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

Bu --data @/dev/fd/<some number>normal bir dosya gibi işlenir gibi görünüyor. Her neyse, yerel olarak çalıştığını görmek istiyorsanız, sadece önce çalıştırın nc -l 8080ve yukarıdaki komuttan farklı bir mermi ateşinde çalıştırın. Gibi bir şey göreceksiniz:

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  }

Gördüğünüz gibi alt kabukları çağırabilirsiniz ve heredoc'ta referansın yanı sıra ne var? Mutlu hack umut bu yardımcı olur '"'"'""""'''""''.


2
Diğer cevap benim için işe yaramadı çünkü Zabbix'ten bir uyarıda çağırmaya çalışıyordum. Bu mükemmel bir şekilde çözer ve daha temizdir.
0rkan

Ancak kodu bash işlevine koyarsanız: myFunction () {....}?
Hanynowsky

1
bu tarifin sadece komut dosyası kelimesi kelimesine (örneğin, EOF, parantezler vb. yeniden biçimlendirme yok) kopyalandıysa işe yaradığını belirtmek gerekir
Vader B

9

Birkaç yıl geç kaldı, ancak eval veya backtick ikamesi kullanıyorsanız birisine yardımcı olabilir:

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

Yanıtın başından ve sonundan tırnak işaretleri ayırmak için sed kullanma

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

4
  • Sir Athos bilgi mükemmel çalıştı!

CouchDB için benim curl betiğimde nasıl kullanmak zorunda kaldım. Gerçekten çok yardımcı oldu. Teşekkürler!

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

4

Buradaki yanıtlardan rehberlik ettikten sonra benim için gerçekten işe yarayan şey:

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

Mevcut cevaplar, curl'un bir dosyadan veri gönderebileceğini ve aşırı alıntılardan kaçınmak ve JSON'u yeni satırlara ayırmak için yorumlu metinler kullanabileceğini gösteriyor. Bununla birlikte, curl standart girdiden veri yayınlayabileceğinden, bir işlev tanımlamaya veya cat'den çıktı yakalamaya gerek yoktur. Bu formu çok okunabilir buluyorum:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.