본문으로 건너뛰기
mcpd
데몬 없음
소스

운영하기

mcpd는 파일 하나를 쥐고 있는 프로세스 하나입니다. 그래서 운영 이야기는 대부분 짧고, 정말 중요한 몇 가지는 정확히 알아 둘 값이 있습니다.

포트 위에 있는 것

주소 하나가 전부를 서비스합니다. /v1/traces, /v1/logs, /v1/metrics의 OTLP 수집, /v1/ingest의 네이티브 수집, /v1/api 아래의 쿼리 API, /의 운영자 인터페이스, 그리고 아래의 운영용 엔드포인트 세 개입니다. 사이드카도 없고 설정할 리버스 프록시도 없습니다. 배포가 한 줄에 들어가는 이유가 대부분 이것입니다.

인터페이스는 바이너리 안에 컴파일되어 있으므로 정적 파일 서버도, 두 번째 볼륨 마운트도 없습니다. 수집에는 큰 본문 한계가 걸려 있고 CORS는 없습니다. 쿼리 API에는 CORS가 있으므로, 다른 오리진에서 서비스되는 인터페이스도 읽을 수 있습니다.

/healthz와 /readyz는 같은 질문이 아닙니다

둘이 나뉘어 있는 이유는 결과가 서로 다르기 때문이며, 둘을 같은 핸들러에 묶는 것은 재시작 루프를 만드는 흔한 방법입니다.

엔드포인트 스토리지를 건드리는가 무엇에 답하는가
GET /healthz 아니요 프로세스가 서비스 중이면 언제나 200
GET /readyz 예, 스토어마다 읽기 한 번 시그널 스토어와 실행 스토어가 답하면 200, 어느 하나라도 답하지 않으면 503

/healthz는 라이브니스입니다. 스토리지를 절대 건드리지 않는 것은 의도한 것입니다. 느리거나 잠긴 데이터베이스 때문에 프로세스가 죽고 다시 시작되어서는 안 됩니다. 재시작이 디스크를 고쳐 주지도 않고, 재시작 루프는 처리 중이던 배치까지 잃게 하기 때문입니다.

/readyz는 레디니스입니다. 리더 커넥션에 대고 아주 가벼운 쿼리를 한 번 돌리므로, 서비스할 수 없는 인스턴스에는 트래픽이 더 가지 않습니다. 스토리지에 닿을 수 없으면 status가 degraded이고 실패를 짚는 detail이 담긴 503으로 답합니다. 상태 코드만 덩그러니 받고 아무것도 모르는 채 조사에 들어가는 대신입니다.

두 응답 본문은 같은 필드를 담습니다. status, version, spec_version, uptime_seconds, storage, 그리고 문제가 있을 때의 detail입니다. spec_version은 이 빌드가 구현하는 데이터 모델의 버전이며, 클라이언트가 이해하지 못하는 서버와는 이야기하지 않겠다고 판단하는 근거가 됩니다.

정상 인스턴스 확인
$ curl -s localhost:4317/healthz{"status":"ok","version":"0.1.0","spec_version":"1.0.0", "uptime_seconds":86400,"storage":"sqlite"}$ curl -s -o /dev/null -w "%{http_code}\n" localhost:4317/readyz200$ curl -s localhost:4317/metrics | head -4# HELP mcpd_signals_accepted_total Signals written to storage.# TYPE mcpd_signals_accepted_total countermcpd_signals_accepted_total 184203# HELP mcpd_signals_rejected_total Signals refused, with a reason returned to the sender.

두 프로브 모두 키가 필요 없고, /metrics도 마찬가지입니다. 운영하는 네트워크에서 그것이 받아들일 수 없는 조건이라면 인그레스에서 제한하십시오.

kubernetes

livenessProbe:
  httpGet: { path: /healthz, port: 4317 }
  periodSeconds: 10
readinessProbe:
  httpGet: { path: /readyz, port: 4317 }
  periodSeconds: 5

# SIGTERM is handled, so give in-flight ingest time to finish.
terminationGracePeriodSeconds: 30

메트릭

mcpd는 자기 카운터를 /metrics에서 Prometheus 텍스트 노출 형식으로 내보냅니다. 기능 플래그 뒤에 있지 않습니다. 관측당할 수 없는 관측 도구는 부채이기 때문입니다.

메트릭 타입 뜻
mcpd_signals_accepted_total counter 스토리지에 기록된 시그널
mcpd_signals_rejected_total counter 거부된 시그널. 보내는 쪽에 이유가 돌아갑니다
mcpd_batches_duplicate_total counter 재전송으로 인식되어 건너뛴 배치
mcpd_traces_sampled_out_total counter 샘플링 정책이 버린 트레이스
mcpd_signals_over_quota_total counter 프로젝트의 분당 상한을 넘겨 거부된 시그널
mcpd_signals_unbounded_total counter 어떤 상한도 덮지 않는 프로젝트로 상한 검사 단계에 이른 시그널
mcpd_ingest_requests_total counter 처리한 수집 요청
mcpd_query_requests_total counter 처리한 쿼리 요청
mcpd_request_errors_total counter 서버 오류로 실패한 요청
mcpd_audit_write_failures_total counter 쓰지 못한 감사 행. 그 행이 설명하는 요청 자체는 성공했습니다
mcpd_uptime_seconds gauge 이 프로세스가 시작한 뒤로 지난 초

모든 카운터는 프로세스 수명 단위이고 재시작하면 0으로 돌아가므로, 값 자체가 아니라 증가율에 알림을 거십시오. 지켜볼 만한 둘은 mcpd_signals_rejected_total과 mcpd_request_errors_total입니다. 앞의 것은 발신자가 거절을 듣고 있는데 아마 응답을 읽지 않고 있다는 뜻이고, 뒤의 것은 정의상 mcpd 자신의 잘못입니다. 4xx는 호출한 쪽의 잘못이고 거기에 세지 않습니다.

mcpd_traces_sampled_out_total이 오르는 것은 결함이 아닙니다. 누군가 자기 실행이 왜 없느냐고 물을 때, 인터페이스의 빈자리를 설명해 주는 숫자입니다.

mcpd_signals_over_quota_total은 시그널이 도착하지 않는 다른 이유, 즉 프로젝트가 분당 상한에 닿은 경우를 같은 모양으로 세는 숫자입니다. 그 거부는 mcpd_signals_rejected_total에도 함께 세지므로, 제한에 걸린 발신자 무리와 잘못된 형식의 데이터를 보내는 발신자 무리를 갈라 보려면 이쪽을 지켜보십시오. 상한이 무엇을 덮는지는 설정에 있습니다.

mcpd_signals_unbounded_total은 그 반대편 숫자입니다. 지목한 프로젝트를 덮는 상한이 없어서 그대로 보관된 시그널입니다. projects 아래에만 적힌 상한은 거기 이름이 있는 프로젝트만 묶으므로, 다른 이름을 지목하는 발신자는 그 옆을 그냥 지나갑니다. 그런 시그널은 거부되는 대신 세어집니다. 아무도 적어 두지 않은 프로젝트를 거부하면 설정을 바꾸지 않고 업그레이드한 배포의 데이터를 버리게 되기 때문입니다. 0이 아니라면 프로젝트별 상한 옆에 최상위 --quota-per-minute를 두십시오.

상한은 행이 들어올 수 있는 모든 창구를 덮습니다. 수집 엔드포인트 네 개, 단건 점수와 피드백 엔드포인트, 그리고 POST /v1/api/score입니다. 마지막 것은 점수를 계산한 다음 저장하기 전에 같은 카운터에 청구합니다. 거기에서 상한 안에 들어가지 못한 것은 상한을 넘겨 기록되는 대신 응답의 skipped 목록에 점수별로 보고됩니다.

mcpd_audit_write_failures_total은 쓰지 못한 감사 행을 셉니다. 각 행이 설명하던 요청은 성공했고 데이터도 돌려주었습니다. 그것이 요점입니다. 감사 쓰기가 그것이 설명하는 읽기를 실패시키는 일은 없습니다. 따라서 0이 아니라는 것은 감사 로그가 설명하지 못하는 저장 페이로드 읽기가 있었다는 뜻이므로, 가용성 신호가 아니라 무결성 신호로 다루십시오.

prometheus

scrape_configs:
  - job_name: mcpd
    static_configs:
      - targets: ['mcpd:4317']

종료

mcpd는 SIGTERM과 SIGINT를 처리합니다. 둘 중 무엇이든 받으면 새 연결을 받지 않고, 처리 중인 요청이 끝날 때까지 기다린 다음 프로세스를 끝냅니다.

특히 SIGTERM을 처리한다는 점이 오케스트레이터 아래에서 이것을 동작하게 합니다. Kubernetes는 SIGTERM을 보내고 유예 시간을 다 기다린 뒤에 SIGKILL을 보냅니다. SIGINT만 듣는 컨테이너는 멈추는 것이 아니라 죽임을 당하고, 트랜잭션 도중이던 배치는 사라집니다.

정상 종료
mcpd 0.1.0 listening on http://0.0.0.0:4317  storage     sqlite at /data/mcpd.dbretention removed 12480 rows older than 30 daysreceived termination signalshutting down

mcpd가 나가는 길에 구해 낼 수 없는 것은 아직 발신자의 큐에 남아 있는 것입니다. SDK는 스팬을 메모리에 들고 있다가 워커에서 내보내므로, shutdown()을 부르지 않고 끝나는 프로세스는 아직 나가지 않은 것을 잃습니다. 그것은 데몬이 아니라 에이전트가 제대로 해야 할 종료입니다.

백업

스토어 전체는 --data에 있는 SQLite 파일 하나입니다. WAL 모드로 도므로 디스크에는 mcpd.db 옆에 mcpd.db-wal과 mcpd.db-shm이 함께 있습니다. 프로세스가 도는 동안 .db만 복사하면 아직 쓰기 선행 로그에 있는 것이 전부 빠진 파일을 얻게 됩니다.

백업은 SQLite를 통해 뜨십시오. mcpd가 계속 쓰는 동안에도 일관된 스냅숏을 읽습니다.

핫 백업

sqlite3 /data/mcpd.db ".backup '/backup/mcpd-$(date +%F).db'"

프로세스를 먼저 멈추고 파일 세 개를 모두 복사하는 것도 똑같이 유효하며, 이미지 안에 sqlite3 바이너리가 없어도 됩니다. 이 빌드에는 mcpd backup 하위 명령도 없고 예약 백업도 없습니다. 이것은 스냅숏 도구가 할 일이고, 아닌 척하면 절반만 만든 백업이 중요한 경로에 들어앉게 됩니다.

보존 처리는 행을 지우지만 파일을 줄이지는 않습니다. SQLite는 비워진 페이지를 들고 있다가 다시 쓰므로, 큰 삭제 뒤에도 디스크 사용량은 줄어들지 않고 평평해집니다. 공간을 정말 돌려받아야 한다면 멈춰 둔 인스턴스에 대고 VACUUM을 돌리십시오.

복구

백업을 되돌리는 일은 네 단계이며, 쓰기 선행 로그 때문에 순서가 중요합니다.

  1. 데몬을 멈추십시오. 도는 프로세스 아래에서 하는 복구는 같은 파일에 대한 두 번째 기록자입니다.
  2. --data에 있는 파일 위에 백업을 복사하십시오.
  3. 옆에 있는 -wal과 -shm 파일을 지우십시오. 그것들은 갈아치운 데이터베이스의 것이고, 그대로 두면 방금 복구한 데이터베이스에 다시 재생됩니다.
  4. 데몬을 시작하고, 복구한 파일을 읽고 있는지 확인하십시오. /readyz가 200으로 답하고, 그 프로젝트에 대한 트레이스 목록이 백업이 담고 있던 실행을 돌려주면 됩니다.
복원, 데모 저장소에서 실행
$ kill $(cat mcpd.pid) && cp /backup/mcpd-2026-09-01.db /data/mcpd.db$ rm -f /data/mcpd.db-wal /data/mcpd.db-shm$ mcpd --data /data/mcpd.db &$ curl -s -o /dev/null -w "%{http_code}\n" localhost:4317/readyz200$ curl -s "localhost:4317/v1/api/traces?project=default&limit=500" | jq ".traces | length"2

업그레이드

바이너리나 이미지 태그를 바꾸고 다시 시작하십시오. 스키마는 시작할 때마다 적용되며, 이미 최신인 파일에 적용해도 아무것도 바뀌지 않도록 쓰여 있습니다. 적용된 버전은 같은 파일 안의 schema_version 테이블에 기록되고, 이 빌드는 버전 2입니다.

기억해 둘 것이 둘 있습니다. 앞으로만 굴리고 뒤로는 굴리지 마십시오. 옛 바이너리가 새 파일을 읽는다는 약속은 없으니 백업을 먼저 뜨십시오. 그리고 SDK 버전을 고정해 쓴다면 업그레이드 뒤에 /healthz의 spec_version을 확인하십시오. 클라이언트가 비교하는 숫자가 그것입니다.

인스턴스 하나가 한계에 닿는 곳

이 점에 대해 정직한 편이, 재 본 적 없는 숫자를 대는 것보다 쓸모 있습니다. 처리량 수치는 내지 않습니다. 우리가 책임질 수 있는 수치가 없기 때문입니다.

  • 기록자는 하나입니다. SQLite 스토어는 뮤텍스 뒤에 쓰기 커넥션 하나와 읽기 커넥션 네 개를 둡니다. WAL 모드 덕분에 대시보드 쿼리가 수집을 막는 일은 없습니다. 그것이 문제가 될 실패였겠지요. 다만 모든 쓰기는 그 커넥션 하나를 통해 직렬화됩니다.
  • 파일 하나에 인스턴스 하나입니다. mcpd 프로세스 두 개가 같은 파일을 가리키는 것은 지원하는 배포가 아닙니다. 수평으로 늘리는 서비스가 아니라 볼륨을 붙인 단일 레플리카로 돌리십시오.
  • 위의 두 한계는 내장 스토어의 것입니다. ClickHouse에서는 적용되지 않으며, ClickHouse는 함께 컴파일되어 있고 아래에서 다룹니다.
  • 페이로드는 큽니다. 프롬프트와 컴플리션은 바이트가 아니라 킬로바이트 단위이고, 그것이 mcpd를 돌릴 만하게 만드는 것입니다. 저장 용량은 스팬 개수보다 텍스트 양에 훨씬 빠르게 따라 커지므로, 초당 스팬 수가 아니라 실제 페이로드로 재십시오.
  • 보존은 적어 둔 프로젝트를 덮습니다. 한 시간 주기 처리는 projects 블록의 모든 프로젝트에서 지웁니다. 각 프로젝트가 retention_days를 정했으면 그 값으로, 정하지 않았으면 전역 값으로 지우며, --project가 지목한 프로젝트도 함께 지웁니다. 발신자가 지어낸 프로젝트가 두 곳 어디에도 없으면 기간이 없어 절대 정리되지 않습니다. 보존을 프라이버시 통제 수단으로 삼기 전에 알아 둘 만합니다.

양이 인스턴스를 넘어서면, 값을 적게 치르는 순서대로 손잡이는 이렇습니다. 파일 크기를 묶는 --retention-days, 들어오는 양을 묶으면서 결정론적이라 남긴 트레이스는 통째로 남기는 --sample, 그리고 단일 기록자와 단일 레플리카를 함께 없애는 ClickHouse로의 이전입니다. 샘플링과 마스킹과 보존 기간을 보십시오.

이미 Postgres를 돌리고 있다면

mcpd를 Postgres 연결 문자열로 향하게 하면 내장 파일 대신 거기에 저장합니다. 스키마는 시작할 때 만들어집니다.

Postgres에 저장하기

mcpd serve --postgres-url postgres://mcpd:$PGPASSWORD@db:5432/mcpd

ClickHouse가 없애는 것과 같은 두 한계를 없앱니다. 쓰기가 더 이상 커넥션 하나를 지나가지 않으므로 mcpd는 서비스 하나 뒤에서 여러 레플리카로 돌고, 그것도 대부분의 팀이 이미 운영하고 백업하고 감시하는 데이터베이스 위에서 돕니다.

마이그레이션은 Postgres 어드바이저리 락을 잡고, 스키마가 이미 최신이면 통째로 건너뜁니다. 그래서 여러 레플리카가 한꺼번에 시작해도 안전하고, 롤링 배포가 다른 레플리카가 쓰고 있는 테이블에 배타 락을 잡는 일도 없습니다.

전문 검색은 GIN 인덱스를 붙인 생성 tsvector 컬럼을 쓰며 설정은 simple입니다. 소문자로 바꾸고 단어 경계로 나누되 어간 추출은 하지 않으므로, 프롬프트에 들어간 그 토큰을 그대로 찾으면 기대한 대로 동작합니다.

보존 기간을 수십억 스팬 단위로 재게 되었을 때 Postgres 대신 ClickHouse를 고르십시오. 그 아래에서는 이미 돌리고 있는 데이터베이스가 더 나은 답입니다.

파일이 더 이상 맞는 모양이 아닐 때의 ClickHouse

mcpd를 ClickHouse HTTP 엔드포인트로 향하게 하면 내장 파일 대신 거기에 저장합니다. 스키마는 시작할 때 만들어지므로 손으로 적용할 것이 없습니다.

ClickHouse에 저장하기

mcpd serve \ --clickhouse-url http://clickhouse:8123 \ --clickhouse-database mcpd \ --clickhouse-user default --clickhouse-password $CH_PASSWORD

위의 두 제약이 한꺼번에 풀립니다. 쓰기가 더 이상 커넥션 하나를 지나가지 않으므로 mcpd는 서비스 하나 뒤에서 여러 레플리카로 돌고, 스팬은 이 데이터가 실제로 가지는 모양에 맞춰 만든 MergeTree에 들어갑니다. 읽기보다 쓰기가 훨씬 많고, 쿼리는 시간 범위를 훑는 모양입니다.

보존 기간을 노트북 디스크가 아니라 실서비스 트래픽 몇 달로 재게 되었을 때 고르십시오. 그보다 작은 곳에서는 내장 파일이 돌리기도 빠르고, 백업하기도 빠르고, 운영할 것이 하나 적습니다. 파일이 아파질 때까지는 파일로 두십시오.

트레이스는 ReplacingMergeTree입니다. 트레이스 투영은 스팬이 도착할 때마다 다시 계산되고 마지막 쓰기가 옳은 값이기 때문입니다. 그래서 순서가 뒤바뀌어 도착하거나, 재시도되거나, 제자리에서 갱신된 스팬도 중복을 쌓는 대신 옳은 답으로 수렴합니다.

여기에서만 다른 두 백엔드보다 약해지는 보장이 하나 있고, 그것은 언젠가 증명해야 할 수도 있는 보장입니다. ClickHouse에서 삭제는 비동기 뮤테이션이므로 삭제 요청은 받아들여진 뒤에 적용됩니다. SQLite와 Postgres는 응답한 그 트랜잭션 안에서 지웁니다. 둘 중 어느 쪽이었는지는 응답의 deletes_pending이 말해 줍니다. 마스킹과 보존 기간을 보십시오.

배포 점검하기

mcpd doctor는 설정과 스토어를 읽고 무엇이 잘못되었는지 보고하며, 각각을 고치는 플래그를 이름으로 짚습니다. 실제로 무는 실패는 조용한 실패이기 때문에 이 명령이 있습니다. 아무것도 죽지 않고, 몇 주 뒤에야 알게 됩니다.

스토어 말고는 아무것에도 접속하지 않고 배포 점검하기

mcpd doctor --data /data/mcpd.db --offline

플래그 세 개는 이 명령만의 것입니다. --offline은 스토어 말고는 아무것에도 접속하지 않으므로, 전달 엔드포인트는 검사되는 대신 건너뛴 것으로 보고됩니다. --read-only는 아무것도 쓰지 않으므로 스토리지 검사는 스토어를 읽을 수 있다는 것만 증명하고 쓸 수 있다는 것은 증명하지 않으며, 그렇다고 말해 줍니다. --window-days는 활동, 시계, 가격표 검사가 며칠치 이력을 읽을지이며, 달리 말하지 않으면 7일이고 1과 36525 사이의 값입니다. 그 밖에 받는 것은 모두 데몬 자신의 설정이므로, 실제로 시작하게 될 바로 그 호출을 채점합니다.

열두 묶음을 이 순서로 채점하고, 보고서 끝에는 등급별 개수가 붙습니다.

묶음무엇을 채점하는가
storage 스토어가 핑에 답하는지, 그리고 프로브 스팬이 쓰기와 읽기와 삭제를 견디는지
runs 실행 스토어가 답하는지, 정의 버전과 도는 실행을 몇 개나 들고 있는지, 그리고 남들이 닿을 수 있는 주소에서 실행 표면이 키를 요구해야 하는지. 읽기만 합니다. 닥터는 단계를 확보하지도, 기한을 발동시키지도 않습니다
keys 모든 스코프와, 무엇을 물려받고 있는지를 드러내어 보여 줍니다. 관리자 키가 없어서 모든 읽기 키가 삭제까지 하게 되는 경우가 문서가 아니라 화면에 나오도록
identity 감사 주체 헤더, 그리고 그것을 설정하도록 허락된 범위가 믿을 만큼 좁은지
projects 설정된 프로젝트와 실행을 담고 있는 프로젝트의 대조. 스팬을 한 번도 받아 본 적 없는 프로젝트는 거의 언제나 이름의 오타입니다
retention 각 프로젝트의 데이터가 얼마나 옛날까지 거슬러 가는지, 그리고 그것을 언젠가 지울 것이 있기는 한지
limits 프로젝트별 수집 상한과 샘플링 비율
forwarding 스팬이 하나도 없는 OTLP 배치를 POST해 보는 것으로 전달 엔드포인트를 검사
judge 판정 모델 블록. 설정으로서만 봅니다
monitors 모니터와 목표, 그리고 그것들이 읽는 시그널
clock 각 프로젝트 이력의 양쪽 끝에 있는 실행을 이 머신의 시계와 대조합니다. 시계가 뒤처진 발신자는 정직한 실행 모두의 아래에 정렬되어, 최신 실행을 보여 주는 페이지에는 절대 나타나지 않기 때문입니다
pricing 최근 모델 스팬을 가격표와 대조하여, 값을 매길 수 없는 모델을 이름으로 짚습니다

identity와 limits는 가장 최근에 더해진 둘이며, 둘 다 같은 이유로 채점되지 않고 있었습니다. 그 어느 것도 죽지 않기 때문입니다. 주체가 없는 감사 로그는 무엇이 행해졌는지는 기록하고 누가 했는지는 결코 기록하지 않습니다. 0.0에서 1.0을 벗어난 샘플링 비율은 --sample 에서는 거부되지만 프로젝트 블록에서는 검사된 적이 없어서, 프로젝트가 그런 값을 지니고 있어도 데몬이 그대로 돌았습니다. 프로젝트별로만 상한을 두고 최상위 상한을 옆에 두지 않으면 아무도 적어 두지 않은 프로젝트는 상한이 전혀 없이 남고, 프로젝트 이름은 발신자가 고릅니다.

건너뜀은 정상이 아닙니다

돌지 않은 검사는 정상이 아니라 건너뜀이라고 말합니다. 그 구분이 이 명령의 요점입니다. 가리킨 설정에 빠져 있는 하위 시스템은 건강한 하위 시스템이 아니며, 둘을 같은 방식으로 보고하면 닥터는 엉뚱한 파일을 받았을 때 가장 자신만만해집니다. 요약 줄은 건너뛴 검사를 따로 세고 말로도 그렇게 적으므로, 열네 가지 발견 가운데 둘을 검증한 실행이 깨끗한 건강 증명서처럼 읽히는 일은 없습니다.

새 배포에서 실행이 끝나는 방식
$ mcpd doctor --data /data/mcpd.db | tail -42 ok, 9 skipped, 2 warnings, 1 faultA skipped check proved nothing: it was not run, or there was nothing thereto run it against. Only the 2 ok were verified.A fault is something broken or open. Exiting 2.

바쁜 스토어가 망가진 스토어는 아닙니다

스토리지 프로브는 쓰기 락이 필요한 유일한 검사입니다. 그 아래는 전부 읽기이고, 읽는 쪽은 쓰는 쪽 뒤에 줄을 서지 않습니다. 그 락을 두고 벌인 경쟁에서 진 프로브 쓰기는 건너뜀으로 보고됩니다. 세 번 시도하고, 세 번 모두 락을 기다리다 포기하면 보고서는 쓰기가 검사되지 않았다는 것과 그 이유를 적습니다.

이것이 중요한 이유는 내장 스토어가 기록자를 하나만 받고, 실제 수집이 도는 배포는 그 락을 거의 쉬지 않고 쥐고 있기 때문입니다. 경합을 결함으로 보고하던 시절에는 배포가 건강하고 바쁜 바로 그때 이 명령이 배포를 막았습니다. 이 프로브가 잡으려는 실패들은 각자 자기 이름을 대며, 그중 어느 것도 "locked"라고 말하지 않습니다. 읽기 전용 마운트, 가득 찬 디스크, INSERT 권한이 없는 역할은 여전히 결함이고, 망가진 락도 마찬가지입니다. 그것은 "locking protocol"이라고 말하며 진짜 손상입니다.

종료 코드

결함이 있으면 0이 아닌 값으로 끝나므로 배포를 막는 관문으로 쓸 수 있습니다. 경고는 결함이 아닙니다. 0으로 끝나고, 사람이 읽기를 기대합니다. 경고가 아니라 결함으로 다루는 구성이 하나 있고, 이것은 이 명령을 파이프라인에 엮기 전에 알아 둘 만합니다. 루프백이 아닌 주소에서 읽기 스코프가 열려 있는 경우로, 포트에 닿을 수 있는 누구에게나 저장된 프롬프트를 전부 넘기는 구성입니다. 같은 주소에서 수집 스코프가 열려 있는 것은 경고로 남습니다. 쓰레기 행은 보존 처리가 지워 주지만 공개된 것은 되돌릴 수 없기 때문입니다. 인터넷 전체를 담고 있는 신뢰 신원 범위도 같은 이유로 같게 채점됩니다. 그러면 어떤 주소든 그 헤더를 설정하고 자기가 대는 이름으로 기록될 수 있습니다.

닿을 수 있게 되기 전에 확인할 설정

mcpd는 루프백이 아닌 주소에 바인드하면, 닿아서는 안 될 호출자에게 열려 있는 표면마다 시작할 때 경고를 로그에 남기고, 각 경고는 설정할 플래그를 이름으로 짚습니다. 시작을 거부하지 않고 경고만 하는 이유는, 거부하면 아무것도 없는 상태에서 첫 트레이스까지 가는 길이 끊기기 때문입니다. 그래도 이것은 진짜 구멍에 대한 경고입니다. 열린 읽기 API는 포트에 닿을 수 있는 누구에게나 저장된 프롬프트를 전부 넘깁니다.

mcpd --data /data/mcpd.db --ingest-key $INGEST_KEY --read-key $READ_KEY --execute-key $EXECUTE_KEY --worker-key $WORKER_KEY --admin-key $ADMIN_KEY --retention-days 30

마지막 세 키가 없으면 ingest 키와 read 키도 실행 표면에 닿고, read 키는 삭제도 할 수 있습니다. 각 키에 대한 자세한 내용과, 설정할 수 있는 그 밖의 모든 것은 설정에 있습니다.