core.exec
Запуск процесса напрямую через argv, без shell — метасимволы не интерпретируются.
core.exec запускает cmd с args напрямую через exec(), без `sh -c`: pipes, redirects, glob и подстановки не работают, каждый элемент args передаётся отдельным токеном. Shell-injection поэтому невозможен, но имя исполняемого файла всё равно TRUSTED-ONLY. По умолчанию шаг рапортует changed=true; понизить до no-op можно guard-параметрами creates / unless / onlyif, а для read-only probe — ключом changed_when: false.
Требования
- Rootне требуется
- Сторона
soul-side - Коллекция
soulstack.exec - Категория
exec
exec_subprocessСостояния
core.exec.run — Запустить cmd с args через exec(), без shell.
По умолчанию всегда (verb «выполнить»).
Сработавший guard creates / unless / onlyif удержал шаг no-op; для probe ставьте changed_when: false.
Параметры
| Параметр | Тип | Обяз. / дефолт | Описание |
|---|---|---|---|
cmd | string | required | Имя исполняемого файла (argv[0], без shell). |
args | list<string> | optional | Аргументы argv[1:]. |
cwd | string | optional | Рабочий каталог процесса. |
env | map<string> | optional | Дополнительные переменные окружения (KEY: VALUE). |
creates | string | optional | Idempotency: если файл существует — шаг пропускается (changed=false). |
unless | string | optional | Idempotency: shell-команда; exit=0 → пропуск. |
onlyif | string | optional | Idempotency: shell-команда; exit≠0 → пропуск. |
Пример — Read-only probe: argv без shell, stdout в register
- name: Read kernel release module: core.exec.run register: kernel_release changed_when: false params: cmd: uname args: ["-r"]Пример — Guard creates: маркер на месте → no-op
- name: Initialize data dir once module: core.exec.run params: cmd: /usr/local/bin/app args: ["init", "--data-dir", "/var/lib/app"] creates: /var/lib/app/.initializedOutput
| Поле | Тип | Описание |
|---|---|---|
stdout | string | |
stderr | string | |
exit_code | number |
Заметки
- Guard-параметры проверяются в порядке creates → unless → onlyif; первый сработавший пропускает команду (changed=false, output { skipped: true, reason }).
- non-zero exit основной команды сам по себе не делает шаг failed — это решает failed_when: (например, grep с exit 1 — норма).
- Типичный register:-паттерн — read-only probe с changed_when: false и чтением register.<name>.stdout в последующих where: / failed_when: / output:.
Безопасность и умолчания
- argv-форма без shell: метасимволы ($, `, |, &, ;, >, *) в cmd/args не интерпретируются — значение "x; rm -rf /" в args это один буквальный аргумент, а не команда.
- TRUSTED-ONLY для имени исполняемого файла: cmd (argv[0]) задаёт, какой файл будет запущен, args могут поменять смысл операции; значения из register.* / soulprint.* / input.* допустимы, только если им доверяет автор Destiny.
- Guard unless / onlyif исполняются через `sh -c` — на их строки распространяется тот же запрет на недоверенную интерполяцию, что и у core.cmd; creates shell не использует (только проверка существования пути).
- Модуль не объявляет run_as_root — команда идёт с привилегиями процесса soul-агента; creates снижает побочные эффекты повторов, но проверяет лишь существование пути, а не успех прошлого запуска.