Skip to main content

pd — DataLake CLI

pd(PlantPulse DataLake) is a single entry point command that starts, stops, and diagnoses eight services running inside the DataLake container, renders configuration, and takes backups. Nearly everything the admin console displays is output from this command's --json.

ItemValue
Moduleplantpulse-datalake-cli
LocationInside container at /opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd (in PATH)
On the hostNot present — you must docker exec plantpulse-datalake pd …
docker exec plantpulse-datalake pd status # 하나만 칠 때
/opt/kopens/plantpulse-platform-docker/bin/shell.sh # 여러 개 칠 때 — 셸을 열고 pd … 만 친다
This is not the operator's first entry point

Platform-wide start/stop/restart is managed from /opt/kopens/plantpulse-platform-docker/bin/ on the hostup.sh · down.sh · restart.sh · restart-datalake.sh · status.sh. pd is one layer lower, a tool for managing services inside the container. The container itself runs pd start on startup and pd stop on shutdown, so operators rarely invoke pd start by hand. Most use cases are viewing status and restarting a single service.

30-second summary

Safety level: Read = changes nothing · Modify = alters state · Destructive = removes data or processes.

VerbOne-linerLevel
pd status [서비스] [--wait]Port table. Exits 0 only when all rows are RUNNINGRead
pd doctorCheck environment, secrets, templates, runtime tree (PASS / FAIL / N/A)Read
pd envDirectory and image identity of this node — declaration only, no measurementRead
pd logs [--list] [--lines N] [서비스…]Follow service logsRead
pd storageVolumes, WAL, replication slots, storage size, Kafka retentionRead
pd retentionTable TTL, topic retention, cold tier, archive jobsRead
pd flowKafka consumer group lagRead
pd downtimeUnplanned downtime windows — restarts onlyRead
pd config list · diff · diff --templatesTemplate → path table, runtime vs rendered, host template vs image defaultsRead
pd node status · info · cql · psqlCassandra / PostgreSQL queries and shellsRead
pd backup list · schedule · statusPhysical backup sets, timers, currently runningRead
pd backup restore … --dry-runRestore plan onlyRead
pd start [서비스] · stop · restart [--clean]Start in order, stop in reverse (with stop proof), bothModify
pd config renderActually writes configuration artifactsModify
pd secret rotate VAR=값Credential rotation — invoked by passwd.sh on the host. Do not invoke directlyModify
pd backup · pd backup run --engine E --type full|diffLogical dump, one physical backupModify
pd backup schedule set|resetBackup timer scheduleModify
pd node add · repair · compact · flush · drainCassandra maintenanceModify
pd cleanDelete stopped module logs, temp filesDestructive (logs)
pd kill [--dry-run]SIGKILL all processes under PP_HOMEDestructive
pd recover [파일]DROP pp database and restore from logical dumpDestructive
pd backup restore … --yesRewind data directory to physical backupDestructive
pd node cleanup · remove <host-id>Delete snapshots, remove node from ringDestructive

Options have the same meaning for all verbs.

OptionMeaning
--jsonSingle JSON document for machines, not a human table. Format read by console. Accepted only by specific verbs; attaching to others exits 2 with rejection
--show-secretsconfig diff only. Passwords not masked with ***. Cannot be used with --json
PD_DEBUG=1DEBUG logging. Prepended like PD_DEBUG=1 pd start

Services and startup order

Eight services start in strict order. The authoritative source is services/order.txt alone. pd start runs top-to-bottom; pd stop runs in reverse.

OrderServiceMASTERWORKERInternal componentspd status row (ports)
1storagevalkey → postgres → cassandra → minio(MASTER only)6379 · 5432 · 9042 · 9000
2analyticsspark-master → hive → gravitino → kyuubi (WORKER has spark-worker · kyuubi)7077 · 4440 · 9083 · 19001 · 10000
3messagingkafka · mqtt(HiveMQ)9092 · 1883
4timeseriesengine(TSE) · dashboard(Grafana)7800 · 3000
5cepTomcat7400
6workflowtemporal → kestra7233 · 8233 · 8380
7data-gatewayTomcat5500
8admin-apiAdmin console backend4949
  • After starting each service, wait until its health check returns UP before proceeding to the next (ceiling: storage 1800 seconds, analytics 600 seconds, others 300 seconds).
  • storage and analytics are gatekeepers. If they fail to start, nothing further is attempted and exit 5. Others warn and continue (exit 6 at the end).
  • timeseries is MASTER-only as of 2026-09-05. plantpulse-sql is deprecated as of 2026-09-07 and removed from this list.

Lifecycle

pd status # 전체 표 — 마지막 줄 "0 STOPPED" 면 정상
pd status storage # 서비스 하나의 헬스체크
pd status storage --wait # UP 이 될 때까지 대기

pd start cep # 죽은 서비스 하나 다시 띄우기
pd stop cep # 서비스 하나 내리기 — «멈췄다» 를 증명한다 (30초 + SIGTERM 15초 + SIGKILL 10초)
pd restart cep # stop → (정지가 증명되면) 5초 → start
pd restart cep --clean # 사이에 pd clean
pd restart # 전부 — 몇 분 걸린다. storage 가 먼저 돌아온다

pd status has four states.

StateMeaning
RUNNINGPort is open
STOPPEDPort is closed. A startup window of tens of seconds is normal; check again after 1 minute
UNKNOWNCould not measure — no tool available to check port. Not necessarily dead
DISABLEDShut down via PD_OPTIONS. Exit code is not changed
If pd stop exits with 7, do not pd start immediately

STILL RUNNING means stop proof failed. Starting over a surviving process causes port collision and data corruption. Use pd kill --dry-run to see what remains, then verify empty with pd kill, pd status, and pd start. Do not use FORCE=1 pd start.

The container's Docker HEALTHCHECK does not invoke pd status (too slow and occasionally flaky). Instead it checks whether postgres and cassandra answer actual queries and whether all ports are open. So "docker ps is healthy but pd status is STOPPED" is a startup window or a single transient miss; "unhealthy but pd status all RUNNING" means ports are open but queries fail (pd logs storage).

Diagnostics

pd doctor # 여섯 절 검사. 마지막 줄 FAIL 0 이면 된다
pd env # 디렉터리 · 이미지 정체 (0.25초)
pd logs --list # 따라갈 파일 목록만
pd logs --lines 50 cep # cep 만, 마지막 50줄부터
pd storage # 볼륨 90% 이상이면 FAIL
pd retention # 왜 안 줄어드나 — TTL · 토픽 보존 · 콜드 티어
pd flow # 데이터가 안 들어온다 — 컨슈머 lag
pd downtime # 자꾸 죽는 것 같다 — 계획 밖 정지 기록

pd doctor has six sections: [1] inputs (secrets, node files, image) · [2] tools · [3] config templates (fully rendered?) · [4] runtime tree · [5] TLS material · [6] core ports. N/A reads "unmeasurable here" with reason in parentheses. Missing sidecar files inside the container is normal — values come from environment variables.

pd flow's NA means "never read" not "fell behind." If the MEMB column is 0, no consumer is running; if greater than 0 but the topic is empty, that is normal (nothing to read); if greater than 0 with data in the topic, that is a real warning sign.

Configuration

pd config list # 이 모드의 템플릿 → 경로 표
pd config diff # 런타임 파일 vs 지금 렌더하면 나올 것 (0 같음 / 1 다름 / 3 시크릿 없음 / 4 렌더 실패)
pd config diff --templates # 호스트 템플릿 vs 이미지 기본값 (same / differs / local / missing)
pd config render # 실제로 쓴다 — 그 뒤 pd restart <서비스> 까지가 한 세트

Procedures for changing values and "where to edit" are in how to change configuration. Do not edit artifacts inside the container directly — they disappear after the next pd start.

Cassandra · PostgreSQL node operations

pd node status # nodetool status — UN 이 정상, DN 이면 죽은 노드
pd node status --json # + PostgreSQL 복제 · Valkey 복제 · 워커 명부
pd node info # 노드 상세
pd node cql # cqlsh (cassandra 계정)
pd node psql # psql (postgres OS 사용자)
pd node errors # cassandra debug.log 의 최근 WARN/ERROR
pd node topic # kafka 토픽 "event" describe
pd node tpstats | compactionstats | proxyhistograms | table-stats [ks] | table-histograms <ks> <tbl> | sstable-size <ks> <tbl> | disk
Modifying verbLevelOne-liner
pd node addModifyRaise keyspace RF to number of live nodes (max 3) and repair. Add workers first, then run once on master
pd node repair · repair-table <ks> <tbl>Modify (heavy)Reconcile data inconsistency between nodes
pd node flush · drainModifyFlush writes from memory to disk. drain blocks writes afterward, use only before shutdown
pd node compact [ks] [tbl]Modify (heavy)Merge SSTables
pd node cleanupDestructiveDelete all snapshots + data this node no longer owns
pd node remove <host-id>DestructiveRemove dead node from ring. Do not run on a live node
pd node upgrade · init-cms · train-zstd · cache-clearModifyInstallation procedure, upgrade, OS page cache flush

Backup · Restore

pd backup # PostgreSQL 논리 덤프 → /data1/pp-data/postgres/dump/
pd backup list | schedule | status
pd backup run --engine postgres --type diff
pd backup restore --engine postgres --set <세트> --dry-run # 계획 먼저
pd recover [덤프파일] # pp DB 하나를 논리 덤프로 되돌림 (파괴적)

Procedures are in backup and restore.

Exit codes

CodeMeaning
0Success. status all RUNNING, doctor zero FAIL, config diff no difference
1General failure, "differs," "has issues"
2Usage error — unknown verb, service, option; --json rejected; PP_HOME missing
3Required secret missing — message lists all names. For backup run · restore: "another backup is running"
4Render failed — unsubstituted ${PP_*}; all names listed
5Gatekeeper service (storage · analytics) failed to start; startup halted
6Startup finished but some services not ready
7Stop proof failed (STILL RUNNING)
8Advertisement address is loopback (127.0.0.1) — render rejected

Log format and journal

Every line pd writes has one shape — [시각] [DATALAKE-CLI] [레벨] [동사] 메시지. INFO to stdout, rest to stderr.

pd start · stop · restart · backup each write one JSON line to the event journal plantpulse-datalake-admin-api/logs/pd-events.jsonl, which the console displays as an event timeline. Commands run from the console are logged by actor as operator:<name>.

Legacy name mapping

The collection of scripts in plantpulse-startup was merged into pd on 2026-09-03, and the old directory is no longer in the image.

Old scriptNow
start-daemon.sh · start.shpd start
stop.shpd stop
restart.sh · restart-<module>.shpd restart [서비스]
restart-monitor.shpd restart admin-api
status.shpd status
kill.sh · clean.shpd kill · pd clean
configure.shpd config render
log-viewer.shpd logs
node-<동사>.sh · node-added.sh · node-error.shpd node <동사> · pd node add · pd node errors
secrets/rotate.shpd secret rotate (invoked by passwd.sh on host)
env.sh · env-reset.sh · env-validate.shRemoved — values are reconciled by host sidecar, node files, and compose
prepare-ssl.shplantpulse-certs container handles it → security configuration
PP_OPTIONSPD_OPTIONS (2026-09-07). Old name not read
Do not look for app restart scripts inside the container

Server, Batch, Warehouse, OPC-UA, and AASX are handled in their own containers. The DataLake container has no such modules. Restart apps from the host.

cd /opt/kopens/plantpulse-platform-docker/bin
./restart-server.sh # 또는 restart-batch.sh · restart-warehouse.sh · restart-one.sh <서비스>