플래그, 출력 및 종료 코드
이 규칙은 모든 ironflock 명령에 적용되며, 스크립트는 이 규칙을 믿고 사용할 수 있습니다. 각 명령의 페이지에는 그 명령이 추가하는 내용만 나옵니다.
명령줄은 다음 두 형태 중 하나입니다:
ironflock <group> <verb> [flags] ironflock agent install -c device.flock
ironflock <verb> [flags] ironflock version그룹은 제품입니다. 디바이스 에이전트는 agent, IronFlock 어플라이언스는 appliance, IronFlockOS는 os입니다. 동사는 모든 그룹에서 같은 뜻입니다. 머신 전체에 관한 명령에는 그룹이 없습니다. 동사 없이 ironflock이나 ironflock <group>만 입력하면 도움말이 출력됩니다. 명령의 페이지에 따로 적혀 있지 않은 한 위치 인자를 받는 명령은 없으며, 그 밖의 모든 것은 플래그입니다. login과 device는 예약된 이름입니다. 이 이름은 예약되어 있다고 답하고 종료 코드 2로 끝납니다.
전역 플래그
모든 명령이 다음 플래그를 받습니다. --help를 제외한 모든 플래그는 명령 이름의 앞이나 뒤에 올 수 있습니다. ironflock --json version과 ironflock version --json은 같습니다.
| 플래그 | 의미 |
|---|---|
--download-base <url> | 다운로드의 기본 URL. 기본값: IronFlock 클라우드 https://instance-registry.ironflock.com/dl. IronFlock 어플라이언스의 디바이스에서는 일부 명령이 어플라이언스의 미러를 먼저 사용합니다. 다운로드 베이스를 참조하십시오. |
--host [user@]machine | 명령을 이 머신 대신 해당 머신에서 SSH로 실행합니다. 여러 머신이면 여러 번 지정합니다. SSH를 통한 원격 머신을 참조하십시오. |
--hosts <file> | 파일에 나열된 각 머신에서 명령을 실행합니다. 한 줄에 [user@]machine 하나씩 적습니다. 호스트 파일을 참조하십시오. |
--parallel <n> | --host와 --hosts의 머신 중 최대 n대에서 동시에 실행합니다. 기본값 10, 1~100. |
--json | 결과를 하나의 JSON 객체로 stdout에 쓰고, 아무것도 묻지 않습니다. |
--yes | 명령의 질문에 예로 답합니다. 거부를 해제하지는 않습니다. |
-h, --help | 명령의 도움말을 출력합니다. |
이름이 고정된 플래그
플래그 이름은 그 플래그가 있는 모든 명령에서 같은 뜻입니다. 짧은 플래그는 -h 외에 -c와 -d뿐입니다.
| 플래그 | 의미 | 명령 |
|---|---|---|
-c, --config <file> | 디바이스의 .flock 파일 | agent install, agent configure, doctor, os flash, os install, os reset |
-d, --drive <drive> | 명령이 쓰는 드라이브 | os flash |
--disk <disk> | 실행 중인 시스템이 시작된 디스크로, 명령이 교체하는 디스크 | os install |
--output <file> | 명령이 드라이브 대신 쓰는 파일 | os flash |
--http-proxy, --https-proxy, --no-proxy | 회사 프록시 | agent install, agent configure, os install |
--proxy-password-file <file> | 프록시 URL에 있는 사용자의 비밀번호가 한 줄로 들어 있는 파일 또는 파이프 | agent install, agent configure, os install |
다운로드 베이스와 프록시
다운로드 베이스는 --download-base, 그다음 환경 변수 IRONFLOCK_DL_BASE에서 가져오며, 둘 다 없으면 https://instance-registry.ironflock.com/dl입니다. 둘 다 없을 때 agent install, doctor, os install, os update는 클라우드보다 먼저, 디바이스의 .flock 파일이 지정하는 어플라이언스의 다운로드 미러를 사용합니다(IronFlock 어플라이언스의 디바이스).
프록시는 플래그, 그다음 HTTP_PROXY, HTTPS_PROXY, NO_PROXY(또는 소문자 형태)에서 가져옵니다. 예외는 agent configure입니다. 이 명령은 플래그만으로 디바이스의 프록시를 변경하며, 명령의 환경 변수는 여기에 아무 영향도 주지 않습니다. 프록시 URL은 http://proxy.example.com:3128 형태입니다. https://와 socks5://도 사용할 수 있으며, 스킴이 없는 URL은 http://로 간주합니다. 프록시에 로그인이 필요하면 http://[email protected]:3128처럼 URL에 사용자를 지정하고, 비밀번호는 --proxy-password-file로 지정합니다(시크릿 참조). 프록시 뒤에 있는 디바이스는 회사 프록시 환경 사용을 참조하십시오.
출력과 JSON
stdout에는 결과만 담깁니다. 사람이 읽는 짧은 텍스트 하나이거나, --json을 사용하면 한 줄로 된 JSON 객체 정확히 하나입니다. --help도 stdout으로 출력됩니다. 유일한 예외는 로그 자체가 결과인 agent logs입니다. --json을 사용하면 이 명령은 로그 한 줄마다 JSON 객체 하나를 씁니다.
그 밖의 모든 것은 stderr에 담깁니다: 진행 상황, 명령이 실행하는 도구(apt, Docker 설치 프로그램)의 출력, 경고, 질문, 오류.
따라서 리디렉션이나 명령 치환은 결과만 받으며, 조용히 실행하려는 스크립트는 stderr를 리디렉션합니다:
# 결과를 텍스트로 파일에 저장. 진행 상황과 경고는 계속 터미널에 표시됨
ironflock status > result.txt
# stderr의 메시지 없이 결과를 JSON으로 셸 변수에 저장
result=$(ironflock status --json 2>/dev/null)JSON의 필드 이름은 snake_case입니다. 명령이 무언가를 변경했으면 결과에 action 필드가 있습니다. 예를 들면 "installed", "configured", "removed"입니다. 필드는 시간이 지나면서 추가되며, 메이저 버전 안에서는 이름이 바뀌거나 제거되지 않습니다. 결과를 읽는 프로그램은 알지 못하는 필드를 무시합니다. 머신이 여러 대이면 --json은 대신 머신마다 한 줄을 씁니다(SSH를 통한 원격 머신 참조).
진행 상황
오래 걸리는 단계는 진행 정도를 stderr에 표시합니다. 터미널에서는 막대로, 그 밖에는 10%마다 한 줄로 표시합니다. --json을 사용해도 stdout에는 결과인 JSON 객체 정확히 하나만 나오고, stderr에는 진행 상황이 이벤트로, 한 줄에 JSON 객체 하나씩 나옵니다:
{"event":"progress","phase":"writing","done":104857600,"total":412345678}| 필드 | 의미 |
|---|---|
event | progress |
phase | downloading: 이미지 파일 또는 릴리스를 다운로드. checking: 그 SHA-256을 카탈로그와 대조. preparing: 이미지로 os install의 쓰기를 준비. writing: 드라이브(또는 --output의 파일)에 쓰기. verifying: 드라이브(또는 파일)를 다시 읽어 확인. installing: 다른 슬롯에 릴리스를 설치(os update) |
done, total | 바이트 수: downloading, checking, preparing, writing에서는 이미지 파일의 바이트 수, verifying에서는 쓴 이미지의 바이트 수. installing에서는 퍼센트이며 total은 100입니다. |
os install은 재시작 전에 이미지 파일을 두 번 읽습니다. checking은 그 SHA-256을 서명된 카탈로그와 비교하고, preparing은 이미지를 한 번 풀어 IRONFLOCKOS 파티션을 찾고, 디바이스의 .flock 파일과 네트워크 설정을 그 안에 넣고, 쓰기가 디스크에 기록할 내용의 체크섬을 계산합니다. 터미널에서는 Checking과 Preparing으로 표시됩니다.
이벤트는 단계가 시작될 때(done은 0), 정수 퍼센트가 바뀔 때마다, 그리고 단계가 끝날 때(done이 total과 같음) 나옵니다. 이어받는 다운로드는 이미 받은 바이트 수로 건너뜁니다. 경고를 포함해 stderr의 다른 줄은 사람이 읽는 텍스트입니다. 프로그램은 JSON 객체로 파싱되는 줄만 가져오고 나머지는 건너뜁니다.
질문과 확인
머신을 변경하는 명령은 먼저 무엇을 할지 알린 다음 묻습니다:
- 무언가를 제거하거나 덮어쓰는 명령은 먼저 무엇이 없어지는지 알립니다. 설치하는 명령은 먼저 무엇을 설치할지 알립니다.
agent stop은 먼저 에이전트를 중지하면 무엇이 끝나는지 알립니다. --yes는 명령의 모든 질문에 예로 답하고, 명령이 선택지를 제시하는 곳에서는 기본값을 택합니다.- 터미널에서는 질문에 “Yes”가 미리 선택되어 있어 Enter만 눌러도 진행됩니다. 세 질문은 “No”가 미리 선택되어 있어 Enter만 누르면 아무것도 지우거나 제거하지 않습니다: 드라이브를 지우기 전의
os flash,--output의 파일을 교체하기 전의os flash, 그리고agent remove입니다. os reset은 디바이스 이름을,os install은 머신의 호스트 이름을 입력하라고 요구합니다. 그 밖의 입력은 Enter만 누른 경우를 포함해 모두 아니요로 처리됩니다.- 질문이 나타나기 전에 입력한 내용은 버려집니다. 질문에는 명령이 알린 내용을 읽은 뒤에 답하게 됩니다.
- Esc는 아니요로 답합니다. 명령은 아무것도 변경하지 않고 종료 코드 4로 끝납니다. 질문에서 Ctrl-C를 누르면 미리 선택된 답도 포함해 아무 답도 하지 않은 것이 됩니다. 명령은 아무것도 변경하지 않고 종료 코드 130으로 끝납니다.
질문하려면 stdin과 stderr 모두에 터미널이 필요합니다. 터미널이 없으면(파이프, CI, cloud-init 스크립트) 명령은 기다리지도 추측하지도 않습니다. 종료 코드 4로 끝나며 --yes로 확인할 수 있다고 알려 줍니다. 아무것도 묻지 않는 --json에서도 마찬가지입니다. 따라서 스크립트는 --json과 함께 --yes를 지정합니다.
--yes는 거부를 해제하지 않습니다. 명령이 거부하면(종료 코드 3 또는 실패한 검사) 어떤 플래그로도 계속 진행할 수 없습니다. 각 명령이 무엇을 거부하는지는 그 명령의 페이지에 나와 있습니다. 유일한 예외는 내부 디스크로, --drive가 내부 디스크를 지정하면 os flash --allow-internal이 그 디스크에 씁니다.
--host를 사용할 때 터미널에서 명령을 실행하면 질문이 사용자에게 전달됩니다. 여러 머신에서 동시에 실행하면 아무에게도 묻지 않으므로, 질문하는 명령은 --yes가 있어야만 그곳에서 실행됩니다(SSH를 통한 원격 머신 참조).
root 권한
시스템을 변경하는 명령에는 root 권한이 필요합니다. root가 아니면 종료 코드 3으로 끝나며 그 이유를 알려 줍니다. 명령은 sudo를 직접 호출하지 않습니다. --host만 다른 머신에서 호출합니다. 이때 os flash는 입력할 명령줄을 앞에 sudo를 붙여 알려 줍니다.
| 명령 | root |
|---|---|
version, completion, os images, os drives, 모든 --help | 필요 없음 |
status, doctor | 필요 없음. root가 아니면 status는 읽을 수 없는 항목에 unknown (needs root)라고 표시하고, doctor는 그런 검사를 skipped로 표시합니다. sudo로 실행하면 그 항목도 읽습니다. |
agent install, agent configure, agent update, agent remove, agent restart, agent stop, agent start | 필요 |
agent logs | 필요. 읽기만 하지만 읽는 대상은 root만 읽을 수 있습니다 |
os flash | 드라이브에 쓰려면 필요. --output을 사용하면 필요 없음. macOS에서는 드라이브의 raw 디바이스에 쓸 수 있는 사용자라면 root가 필요 없습니다. |
os install, os update, os rollback, os reset | 필요 |
self-update | 바이너리 폴더에 대한 쓰기 권한, 그리고 바이너리의 소유자이면서 그 그룹의 구성원일 것, 또는 root. /usr/local/bin/ironflock이면 root입니다 |
--host를 사용할 때 로그인 계정이 root가 아니면, root가 필요한 명령은 다른 머신에서 sudo를 통해 실행됩니다.
시크릿
어떤 명령도 시크릿을 출력하지 않습니다. .flock 파일의 시크릿, WiFi 암호 문구, 프록시 비밀번호, 라이선스 키 모두 마찬가지입니다. 이는 stdout, stderr, --json, 오류 메시지 모두에 적용됩니다.
명령줄은 ps와 셸 기록에 나타나므로, 파일로 전달할 수 있는 시크릿은 절대 플래그 값으로 받지 않습니다. 프록시 비밀번호도 예외가 아닙니다:
- 플래그에 지정하는 프록시 URL에는 비밀번호 없이 사용자만 지정합니다:
http://[email protected]:3128. http://user:password@proxy:3128처럼 비밀번호가 들어 있는 URL은 잘못된 명령줄입니다(종료 코드 2). 아무것도 실행되기 전에,--host를 사용하면 머신으로 전달되기 전에 거부됩니다. 오류 메시지는 이 URL을 되풀이하지 않습니다.- 비밀번호는
--proxy-password-file에서 가져옵니다. 한 줄로 된 파일 또는 파이프(/dev/stdin)입니다. agent install이 대신 사용하는 환경의 프록시 변수에는 비밀번호가 들어 있어도 됩니다. 명령줄에 나타나지 않기 때문입니다.
# 파일에서 비밀번호 읽기
sudo ironflock agent configure --https-proxy http://[email protected]:3128 --proxy-password-file proxy-password.txt
# 파이프로 비밀번호 전달
sudo ironflock agent configure --proxy-password-file /dev/stdin --yes < proxy-password.txtagent install이 설정한 디바이스에서 프록시 비밀번호는 root만 읽을 수 있는 /etc/ironflock/proxy.env(모드 0600)에 있습니다. docker.service와 ironflock-device-agent.service의 드롭인은 이 파일의 이름만 지정하고 프록시 설정을 담지 않으므로, systemctl show는 모든 사용자에게 파일 이름만 보여 주고 그 내용은 보여 주지 않습니다.
--host를 사용하면 플래그에 지정한 .flock 파일, WiFi 암호 문구 파일, 프록시 비밀번호 파일은 명령줄이 아니라 SSH 연결을 통해 다른 머신으로 전달됩니다(SSH를 통한 원격 머신 참조). 로그인 정보가 들어 있는 다운로드 베이스는 어떤 머신에도 접속하기 전에 종료 코드 2로 끝납니다.
종료 코드
| 코드 | 종류 | 의미 |
|---|---|---|
| 0 | 완료 | |
| 1 | failed | 명령이 시작되었지만 끝까지 완료하지 못함 |
| 2 | usage | 명령줄이 잘못됨: 알 수 없는 명령이나 플래그, 누락된 플래그, 예약된 이름. 아무것도 건드리지 않았습니다. |
| 3 | precondition | 머신이 명령에 필요한 상태가 아님: root가 아님, 에이전트가 설치되지 않음, 에이전트가 이미 설치됨, 명령이 실행되지 않는 시스템. 아무것도 건드리지 않았습니다. |
| 4 | declined | 질문에 아니요로 답했거나, 질문할 수 없었는데 --yes가 지정되지 않음 |
| 130 | interrupted | 명령이 끝나기 전에 중단됨(Ctrl-C). --host에서는 다른 머신의 명령이 행업, 인터럽트 또는 종료 시그널로 끝난 경우도 포함 |
| 255 | ssh | --host의 SSH 연결 실패: 머신에 접속하지 못했거나 연결이 끊김 |
오류는 stderr에 한 줄로 나오며, Error: 뒤에 메시지가 붙습니다. 사용법 오류 다음에는 읽어야 할 --help를 알려 주는 줄이 이어집니다. --json을 사용하면 오류가 곧 결과입니다. stdout에 오류 객체가 나오고 stderr에는 오류 줄이 나오지 않습니다. kind는 표에 있는 종류 중 하나입니다.
{"error":{"kind":"precondition","message":"the agent is not installed on this machine"}}두 명령은 결과를 쓰면서도 종료 코드 1로 끝납니다. agent update는 에이전트가 현재 버전에 머물 때 그렇습니다. 결과에 그 이유가 나오고, stderr에 Error: 줄이 나옵니다. doctor는 검사가 실패했을 때 그렇습니다. 결과에 어떤 검사인지 나오며, 오류 줄은 이어지지 않습니다. 이때는 --json을 사용해도 둘 다 오류 객체를 쓰지 않으며, stdout에 결과가 나옵니다.
--help와 함께 쓰면 알 수 없는 명령도 오류가 아닙니다. ironflock os nosuch --help는 ironflock os의 도움말을 출력하고 종료 코드 0으로 끝납니다. 여러 머신에서 실행하면 명령은 머신들의 종료 코드 중 가장 나쁜 것으로 끝납니다(SSH를 통한 원격 머신 참조).
인터럽트
Ctrl-C, SIGTERM, SIGHUP(터미널이나 SSH 세션이 사라질 때)은 다른 프로그램과 마찬가지로 대부분의 명령을 오류 줄 없이 즉시 끝냅니다. 셸에는 130(SIGTERM 후에는 143, SIGHUP 후에는 129)이 전달됩니다. 일부 단계는 이 시그널을 직접 처리합니다:
- **
os flash**는 이미지를 다운로드하거나 쓰거나 다시 읽는 동안, **os update**는 번들을 다운로드하고 확인하는 동안 다음 블록에서 멈춥니다. 무엇을 남겼는지를 종류가interrupted인 오류로 알리고 130으로 끝납니다. 이때os update는 아무것도 설치하지 않습니다.os flash가 마지막 블록까지 다시 읽은 뒤에는 마무리 단계가 끝까지 진행되고 0으로 끝납니다. Ctrl-C를 한 번 더 누르면 프로세스가 즉시 끝납니다.--output을 사용했다면.part파일이 남을 수 있습니다. - **
agent logs --follow**는 이런 시그널이 올 때까지 로그를 따라가다가 0으로 끝납니다. - **
agent update**는 업데이트 추적을 멈추고 130으로 끝납니다. 에이전트는 혼자서 업데이트를 계속합니다. - **
os reset**은 요청을 쓰는 중이면 요청을 철회하고 130으로 끝나며, 디바이스는 재시작하지 않습니다. - **
agent configure**는 머신을 변경하기 시작한 뒤에는 터미널이나 SSH 세션이 끊겨도 더 이상 멈추지 않습니다. Ctrl-C와 SIGTERM은 여전히 즉시 끝냅니다. - **
os install**은 질문 전과 후에 다르게 동작합니다.ironflock os install을 참조하십시오.
스크립트에서 종료 코드 사용하기
스크립트는 명령이 질문에서 멈추지 않도록 --yes를, 읽을 수 있는 결과를 얻도록 --json을 지정하고, 종료 코드를 확인합니다:
#!/bin/sh
# 에이전트가 자체 업데이트하게 함. JSON 결과는 보관하고 stderr의 진행 상황은 버림.
result=$(sudo ironflock agent update --yes --json 2>/dev/null)
code=$?
case $code in
0) echo "agent is current: $result" ;;
1) echo "agent update failed: $result" ;;
3) echo "agent update refused on this machine: $result" ;;
*) echo "agent update ended with exit code $code: $result" ;;
esac종료 코드 0이면 $result에 결과가 들어 있으며, 그 outcome은 updated 또는 current입니다. 종료 코드 1이면 에이전트가 현재 버전에 머무는 이유를 outcome과 reason으로 알려 주는 결과, 또는 오류 객체가 들어 있습니다. 종료 코드 3이면 오류 객체가 들어 있습니다.