다음 줄은 오류(... request body malformed."}
)를 발생시킵니다. 이는 user-data.yml의 일부이며 생성 시 서버를 부트스트랩하기 위해 Digital Ocean API의 일부로 cloud-init와 함께 사용됩니다.
sed -ie '\$a\ \n\#Add logfile information\nlogfile /var/log/ntp.log' /etc/ntp.conf
기본적으로 다음을 수행해야 합니다.
- 빈 줄 추가
- 다음 줄에 주석 추가
- 다음 줄에 문자열 추가
그래요로드 중 저것 userdata.yml 카니발에서스크립트는 다음과 같습니다.
curl -X POST "https://api.digitalocean.com/v2/droplets" \
-d'{"name":"'$droplet_name'",
"region": "'$region'",
"size": "'$size'",
"image": "'$image'",
"backups":false,
"ipv6":false,
"private_networking":false,
"user_data":
"'"$(cat /user-data.yaml)"'",
"ssh_keys": '$root_ssh_pub_key'}' \
-H "Authorization: Bearer $api_key" \
-H "Content-Type: application/json"
몇 시간 동안 해킹을 하고 나면 코드맹이 될 수도 있습니다.
답변1
귀하의 sed는 내 시스템에 "종료되지 않은 정규식"을 제공합니다. 다음과 같은 작업을 수행할 수 있습니다.
echo abc > xy
sed -ie '$a\\n#Add logfile information\nlogfile /var/log/ntp.log' xy
cat xy
이것은 만든다:
abc
#Add logfile information
logfile /var/log/ntp.log
YAML 업로드에 관해서는 이것이 추가하는 내용에 영향을 미치는지 확실하지 않습니다. 업로드된 데이터를 검사할 수 없는 경우 확장 YAML을 파일 a에 작성한 xyz.yaml
다음 컬을 사용하여 업로드하는 방식으로 생성하는 것이 좋습니다 -d @xyz.yaml
. 이를 통해 업로드하는 콘텐츠가 예상한 것과 정확히 일치하는지 확인할 수 있습니다.
답변2
결국 제가 직접 고쳤습니다...
DO API를 사용하고 다음과 같은 튜토리얼을 따라야 할까요?이것(기사 중간 참조) 다음 오류 중 하나가 발생할 가능성이 높습니다.
오류 1비슷한 문제가 발생합니다 ...request body malformed
. 이 문제를 해결하려면 yaml에서 문자열/문자를 이스케이프 처리하는 것을 잊지 마세요.
오류 2언뜻 보면 아무런 문제가 발생하지 않습니다. API 요청 실행이 완료되고 드롭릿이 회전하며, 특별한 작업을 수행하지 않는 한 이를 눈치채지 못할 수도 있습니다(스크립트가 시스템에 수행하는 작업을 확인하지 않으면...). 그러나 cloud-init의 로그를 확인하면 표시됩니다 failed loading yaml blob
. 이는 이스케이프가 필요한 문자가 충분히 자주 이스케이프되지 않기 때문입니다(?!).
예:
- 이로 인해 오류 1(이스케이프 달러 문자 누락)이 발생합니다.
sed -i -e '$a\ \n#Add logfile information\nlogfile /var/log/ntp.log' /etc/ntp.conf
- 이로 인해 오류 2가 발생합니다(달러는 교묘하게 이스케이프 처리되었지만 여기서는 한 번의 이스케이프만으로는 충분하지 않습니다...).
sed -i -e '\$a\ \n#Add logfile information\nlogfile /var/log/ntp.log' /etc/ntp.conf
따라서 해결책은 다음과 같습니다.
sed -i -e '\\$a\\ \\n#Add logfile information\\nlogfile /var/log/ntp.log' /etc/ntp.conf
실제로 읽고 있는 사람이 있고 내가 얼마나 좌절했는지 이해하는 사람이 있다면 여기서 무슨 일이 일어나고 있는지 설명할 수 있는지 알려주십시오. 배우다.
내가 이해할 수 있는 유일한 이유는 bask 스크립트가 yaml을 가져와 원격 셸을 통해 json으로 보낼 때 더 많은 "주의"가 필요하므로 이중 이스케이프가 필요하다는 것입니다. !
답변3
여러 키와 값이 포함된 JSON 문서를 업로드하려는 것 같습니다. 파일은 다음과 같습니다.보기 흉한 것예를 들어 문자열에 리터럴 개행 문자, 큰따옴표 등 특정 JSON 인코딩이 필요한 문자가 포함된 경우와 같이 값 중 하나라도 유효하지 않은 경우
모든 값이 올바르게 인코딩되도록 하려면 JSON 처리 도구 형식을 사용하는 것이 도움이 될 것입니다.jq
또는jo
. 다양한 문자 등을 이스케이프 처리하여 데이터를 수동으로 준비하는 것보다 이와 같은 도구를 사용하는 것이 더 좋습니다.
사용 jq
:
jq -cn \
--arg name "$droplet_name" \
--arg size "$size" \
--arg image "$image" \
--argjson backups false \
--argjson ipv6 false \
--argjson private_networking false \
--arg user_data "$(cat /user-data.yml)" \
--arg ssh_keys "$root_ssh_pub_key" \
'$ARGS.named'
기본적으로 --arg
모든 문자열뿐만 아니라 --argjson
문자열이 아닌 값(숫자 및 부울)에도 적용됩니다.
/user-data.yml
큰 문서인 경우 jq
명령줄에서 확장하는 대신 읽도록 할 수 있습니다.
jq -cn -Rs \
--arg name "$droplet_name" \
--arg size "$size" \
--arg image "$image" \
--argjson backups false \
--argjson ipv6 false \
--argjson private_networking false \
--arg ssh_keys "$root_ssh_pub_key" \
'$ARGS.named + { user_data: input }' /user-data.yml
이는 또한 파일의 마지막 개행 문자를 보존합니다 /use-data.yml
.
그리고 jo
:
jo \
name="$droplet_name" \
size="$size" \
image="$image" \
backups=false \
ipv6=false \
private_networking=false \
user_data=@/user-data.yml \
ssh_keys="$root_ssh_pub_key"
여기서는 사용자 데이터 파일을 읽고 인코딩하기 위해 @
let을 사용하고 있습니다 . jo
를 사용할 수도 있었지만 use_data="$(cat ...)"
더 많은 입력이 필요했기 때문에 더 짧고 읽기 쉬운 변형을 선택했습니다. 또한 jo
값의 유형을 자동으로 추론하므로 null
빈 문자열 대신 누락된 값을 얻게 됩니다.
어떤 명령을 사용하든 해당 명령의 출력을 다음으로 직접 파이프할 수 있습니다 curl
.
json-generating-command |
curl --silent --show-error \
--header "Authorization: Bearer $api_key" \
--json @- 'some-URL-here'