Pular para o conteúdo

Literais de Comando e Segurança

Nesta página

O literal sh"…" monta um Cmd lazy; ele não inicia um shell nem executa um processo. Chame run() para obter um Result<Output, CmdError> verificado ou run_raw() quando um status diferente de zero for apenas um dado. Estes exemplos exigem a CLI local do Zolo, por isso o runner do navegador fica desativado.

Monta e executa um comando, fornece a entrada padrão e inspeciona um resultado não verificado diferente de zero.

01-command-literals.zolo
Playground
// Feature: sh"…" command literals — Zolo as a typed Bash replacement.

// Syntax: `sh"git status {branch}"` builds a lazy `Cmd` (nothing runs);

// `.run()` executes and returns `Result<Output, CmdError>`.

// When to use: any place you'd reach for a shell script — with types,

// Result-based errors, and injection-safe interpolation for free.


// Lazy: building a command executes nothing.

let cmd = sh"git version"
print("built: {cmd}")

// .run() blocks and returns Result<Output, CmdError> — status ≠ 0 is Err.

match cmd.run() {
  .Ok(out) => print("exit {out.status}: {out.stdout.trim()}"),
  .Err(e) => print("failed [{e.status}]: {e.stderr}"),
}

// Chainable builders: cwd / env / stdin / timeout — each returns a new Cmd.

let hashed = sh"git hash-object --stdin".stdin("hello zolo").run()
match hashed {
  .Ok(out) => print("hash: {out.stdout.trim()}"),
  .Err(e) => print("failed: {e}"),
}

// .run_raw() never raises on status ≠ 0 — the `check=False` escape hatch.

let raw = sh"git definitely-not-a-subcommand".run_raw()
print("run_raw status (non-zero, no Err): {raw.status != 0}")

Requer a CLI/host do Zolo — abra no playground ou rode localmente.

Cada valor interpolado vira uma única entrada opaca de argv. Arrays expandem um elemento por vez, e Raw é a saída explícita para divisão intencional em palavras.

Mostra que texto hostil e nomes de arquivo com espaços continuam sendo argumentos únicos.

02-safe-interpolation.zolo
Playground
// Feature: safe interpolation — the shell-injection class, deleted.

// Syntax: every `{expr}` in sh"…" becomes ONE opaque argv word, never

// re-interpreted by a shell (there is no shell: argv goes straight to the

// OS). `Raw(text)` is the explicit opt-out; arrays splice element-wise.

// When to use: always — it's the default. Compare with the legacy

// `os.execute("cat " + filename)`, where concatenation IS the bug.


// A hostile value stays ONE argument — argv inspection proves it:

let evil = "; rm -rf ~ --oops"
let c = sh"cat {evil}"
let argv = c.__stages[0].argv
print("argv len (cat + 1 opaque arg): {argv.len()}")
print("the whole payload is one word: {argv[1]}")

// Values glue to adjacent literal text and still form one word:

let rev = "deadbeef"
let tagged = sh"docker build -t app:{rev} ."
print("glued word: {tagged.__stages[0].argv[3]}")

// Arrays splice as separate arguments (element boundaries, not spaces):

let files = ["a.txt", "name with spaces.txt"]
let tar = sh"tar -cf out.tar {files}"
print("spaced filename survives as one word: {tar.__stages[0].argv[4]}")

// Raw() — the author takes responsibility; text is word-split like source:

let flags = Raw("-la --color=auto")
let ls = sh"ls {flags}"
print("raw splice words: {ls.__stages[0].argv.len() - 1}")

Requer a CLI/host do Zolo — abra no playground ou rode localmente.

run() usa o tipo Result normal, então scripts com várias etapas podem propagar o primeiro CmdError com ?.

Propaga falhas de comandos e identifica um executável ausente com status -1.

03-typed-result.zolo
Playground
// Feature: Cmd.run() → Result<Output, CmdError> — errors you can type.

// Syntax: status ≠ 0 is already Err; `?` propagates it like any Result.

// Launch failure (missing binary) and timeout use status -1.

// When to use: multi-step scripts where Bash would scatter `$?` checks.


fn describe() -> Result<str, CmdError> {
    // Each step propagates with `?` — first failure short-circuits.

    // (Bind before the field access: `run()?.stdout` would lex as the

    // `?.` optional-chain operator, which is a different thing.)

    let v = sh"git version".run()?
    let version = v.stdout.trim()
    let h = sh"git hash-object --stdin".stdin(version).run()?
    return Result.Ok("{version} -> {h.stdout.trim()}")
}

match describe() {
    Result::Ok(line) => print(line),
    Result::Err(e) => print("step failed [{e.status}]: {e.stderr}"),
}

// Missing binary → Err with status -1 (never a shell "command not found"):

match sh"zolo-example-missing-binary".run() {
    Result::Ok(_) => print("unexpected"),
    Result::Err(e) => print("launch failure status: {e.status}"),
}

Requer a CLI/host do Zolo — abra no playground ou rode localmente.

Buscar no Zolo

9 resultados

enespt-br