<@ULVA73B9P> How do I create a flow for a bin/bash...
# ask-marvin
c
@Marvin How do I create a flow for a bin/bash script in Prefect?
m
thought for 385.9 seconds
n
are you asking how you wrap a bash script in a prefect flow?
c
@Nate yes
n
https://docs.prefect.io/integrations/prefect-shell#integrate-shell-commands-with-prefect-flows
prefect shell watch
Copy code
» uvx prefect shell watch "curl <http://ip.me|ip.me>"
10:54:21.864 | INFO    | Flow run 'magnificent-dinosaur' - Beginning flow run 'magnificent-dinosaur' for flow 'Shell Command'
10:54:21.869 | INFO    | Flow run 'magnificent-dinosaur' - View at <http://127.0.0.1:4200/runs/flow-run/8c4d3976-e2fc-4948-8d69-6874c9dc6317>
10:54:22.259 | INFO    | Flow run 'magnificent-dinosaur' - 73.50.144.240
10:54:22.355 | INFO    | Flow run 'magnificent-dinosaur' - Finished in state Completed()
1
c
@Nate Thank you!
m
Great question! Assuming you’re on Prefect 3.x, you’ve got a few good options to turn a bash script into a Prefect flow. Pick the one that fits your needs best. Option A: Use the prefect-shell integration (simple and ergonomic) - Install once:
Copy code
pip install prefect prefect-shell
- Example flow that runs a bash script and streams logs to the Prefect UI:
Copy code
from prefect import flow
from prefect_shell.commands import shell_run_command

@flow(name="Run Bash Script")
def run_bash_script(script_path: str, *args):
    cmd = f"bash {script_path} {' '.join(args)}".strip()
    output = shell_run_command(
        command=cmd,
        env={"FOO": "bar"},   # optional
        cwd="/path/to/working/dir",  # optional
    )
    return output

if __name__ == "__main__":
    run_bash_script("/path/to/script.sh", "arg1", "arg2")
- Docs: prefect-shell integration Option B: Use Prefect’s built-in process utilities (async, fine-grained control)
Copy code
from prefect import flow, get_run_logger
from prefect.utilities.processutils import run_process

@flow(name="Run Bash Script (processutils)")
async def run_bash_script(script_path: str, *args):
    logger = get_run_logger()
    cmd = ["bash", script_path, *args]
    proc = await run_process(
        cmd,
        stream_output=True,           # stream stdout/stderr to Prefect logs
        env={"FOO": "bar"},           # optional
        cwd="/path/to/working/dir",   # optional
    )
    <http://logger.info|logger.info>(f"Process exited with code: {proc.returncode}")
    return proc.returncode

if __name__ == "__main__":
    import asyncio
    asyncio.run(run_bash_script("/path/to/script.sh", "arg1"))
- API reference: processutils Option C: No Python code — turn a shell command into a flow via CLI - For a one-off observed run:
Copy code
prefect shell watch "bash /path/to/script.sh arg1 arg2"
- To create and serve a deployment (optionally on a schedule):
Copy code
prefect shell serve "bash /path/to/script.sh arg1" --name "Run Bash Script" --deployment-name "bash-script" --cron-schedule "0 12 * * *" --timezone "UTC"
- CLI reference: prefect shell CLI Notes and tips - Working directory and environment: use
cwd=
and
env=
as shown above. - Streaming logs:
prefect-shell
and
run_process(..., stream_output=True)
will stream output to your flow’s logs in the Prefect UI. - Script location: ensure your script is available wherever your flow/worker runs (container, VM, etc.) and is executable if you call it directly. - Reusability: prefect-shell also includes a
ShellOperation
block for storing command configs you can reuse across flows. Would you like to: - Run an existing script file (path/args)? - Schedule it or run on-demand? - Pass specific environment variables or secrets? - Run in Docker/Kubernetes or just locally? Share a bit more about your setup and goals, and I’ll tailor the example and deployment steps.