AutoSys delete_box — One Command Wiped 47 Payroll Jobs
Using delete_box instead of delete_job made 47 payroll jobs vanish.
20+ years shipping production infrastructure and CI/CD at scale. Notes here come from systems that actually shipped.
- ✓Basic programming fundamentals
- ✓A computer with internet access
- ✓Willingness to follow along with examples
- insert_job creates new job definitions. Fails if the job already exists.
- update_job modifies only the attributes you specify — partial update, not replacement.
- delete_job removes a single job. delete_box removes the box plus all child jobs.
- Each command uses JIL syntax; a typo or missing required attribute stops the entire batch.
- Production insight: delete_box is the most dangerous — it silently wipes entire job trees.
- Biggest mistake: assuming update_job is a full rewrite — it's not, and omitted attributes stay unchanged.
AutoSys JIL (Job Information Language) is the command-line interface for defining and managing workload automation jobs in Broadcom's AutoSys Workload Automation platform. JIL subcommands—insert_job, update_job, delete_job, and delete_box—are the raw SQL-like verbs that directly mutate the AutoSys database.
Unlike GUI-based job editors, JIL gives you scriptable, idempotent control over job definitions, which is why a single delete_box command can cascade-delete an entire job hierarchy, including all child jobs and their dependencies. In production environments running thousands of batch jobs—common at banks, insurers, and payroll processors—one mistyped delete_box targeting a parent box can silently wipe out dozens of critical jobs in milliseconds, with no undo.
The insert_job subcommand creates a new job or box definition, requiring at least a job name, job type (e.g., c, cmd, fw), and a command or script path. update_job modifies existing attributes—like changing a start time, adding a condition, or swapping the command—without needing to delete and recreate the job. delete_job removes a single job definition, while delete_box recursively removes the box and all jobs inside it. These operations are immediate and permanent; there's no recycle bin.
The only safety net is the autorep command to preview what you're about to delete, or using -q flags in scripts to simulate changes.
Common pitfalls include forgetting that delete_box is recursive (it does not prompt for confirmation), using update_job without specifying all required fields (which can silently reset unmentioned attributes to defaults), and running JIL commands against production databases without first testing in a non-prod environment. Seasoned AutoSys admins always wrap destructive JIL operations in scripts that first export job definitions to flat files (autorep -J jobname -q > backup.jil), then validate the target job count before executing deletes.
Automation scripts often combine autorep with grep and awk to generate batch JIL files for mass updates—like changing a calendar across 200 jobs—but this power demands rigorous change control, because one bad regex can delete the wrong jobs at scale.
insert_job is like hiring a new employee and filling out their paperwork. update_job is like updating their job description without rehiring them. delete_job is like terminating that employee and removing their record.
Managing jobs in AutoSys means mastering three JIL subcommands: insert_job to create, update_job to modify, and delete_job to remove. These are the bread-and-butter operations you'll perform every week as an AutoSys administrator or developer. You'll see them in every single batch pipeline. And you'll screw them up at least once.
Why One jil Command Can Wipe Out 47 Payroll Jobs
The jil insert, update, and delete operations are the core commands for managing AutoSys job definitions via the command-line interface. Insert creates a new job definition from a JIL script, update modifies an existing job's attributes, and delete removes a job entirely from the AutoSys database. The critical mechanic: these commands operate on the job definition, not the job instance — a delete command removes the job permanently, including all future scheduled runs.
In practice, jil commands are executed against the AutoSys Event Processor, which immediately commits changes to the database. There is no staging area or undo. A single jil delete command with a wildcard or mis-specified job name can remove hundreds of jobs in seconds. The command syntax is straightforward: jil -d "delete_job: job_name" — but the lack of a confirmation prompt is the dangerous part.
Use jil insert/update/delete when you need to programmatically manage job definitions in batch, such as during deployment automation or disaster recovery. The real-world impact: a junior operator running a script with an incorrect job name pattern can delete an entire application's job stream. Production teams must implement strict access controls and always test delete commands in a sandbox environment first.
jil -q "show_job: PAYROLL_*") and require a second operator approval for any delete command targeting more than 5 jobs.insert_job — creating a new job
insert_job creates a brand-new job definition in the AutoSys Event Server. The job name must be unique within the instance. All required attributes (job_type, machine for CMD jobs, owner) must be included. You cannot insert_job if a job with that name already exists — use update_job instead.
insert_job: daily_reconcile job_type: CMD command: /opt/scripts/reconcile.sh machine: finance-server-01 owner: finuser date_conditions: 1 days_of_week: mon-fri start_times: "05:00" std_out_file: /logs/autosys/daily_reconcile.out std_err_file: /logs/autosys/daily_reconcile.err alarm_if_fail: 1 n_retrys: 1 description: "Morning reconciliation run before market open"
autorep -J newjob -q after insertion — a silent failure (like a typo in machine name) can leave the job orphaned.update_job — modifying an existing job
update_job modifies an existing job definition. You only need to include the attributes you want to change — everything else stays as it was. This is a partial update, not a full replacement.
/* Change only the start time — everything else unchanged */ update_job: daily_reconcile start_times: "04:30" /* Add a condition to an existing job */ update_job: generate_report condition: success(daily_reconcile) /* Change the machine a job runs on */ update_job: daily_reconcile machine: finance-server-02
start_times: "").delete_job and delete_box
delete_job removes a single job. delete_box removes a box and ALL jobs inside it. Always back up definitions before deleting.
/* Delete a single job */ delete_job: old_report_job /* Delete a box AND all inner jobs */ delete_box: legacy_eod_box /* SAFER: backup first, then delete */ # autorep -J old_report_job -q > /tmp/old_report_job_backup.jil # Then review the backup, then: delete_job: old_report_job
autorep -J jobname -q > backup.jil before any delete operation. Once a job is deleted from the Event Server, the history is also gone.Common pitfalls when using JIL subcommands
Even experienced AutoSys admins make mistakes with these commands. The most common: confusing insert and update, forgetting that update is partial, running delete_box when you meant delete_job, and not backing up before deletion. Also: JIL syntax is finicky about whitespace. A missing colon after the subcommand attribute name will cause a parse error.
/* WRONG: missing colon after job name */ update_job daily_reconcile /* WRONG: using insert_job on an existing job */ insert_job: daily_reconcile /* WRONG: trying to remove start_times by omitting it */ update_job: daily_reconcile /* Oops — start_times not mentioned, so it stays at 05:00 */
- POST (insert_job) fails if resource exists.
- PATCH (update_job) only changes included fields.
- DELETE (delete_job) removes one resource.
- Cascading DELETE (delete_box) removes a collection and all its children.
Automating job lifecycle management with scripts
In production, you'll rarely run JIL commands one by one. Instead, you'll build scripts that generate JIL files dynamically and pipe them to the jil command. A common pattern: loop over a list of jobs, check existence, then choose insert or update. Another: after a code deployment, you update batch schedules en masse by generating JIL from a template.
#!/bin/bash # Example: deploy new job or update existing JOB_NAME="daily_reconcile" JIL_FILE="/tmp/${JOB_NAME}.jil" # Check if job exists autorep -J "$JOB_NAME" -q > /dev/null 2>&1 if [ $? -eq 0 ]; then echo "Job exists — using update_job" cat > "$JIL_FILE" <<EOF update_job: $JOB_NAME start_times: "06:00" EOF else echo "Job does not exist — using insert_job" cat > "$JIL_FILE" <<EOF insert_job: $JOB_NAME job_type: CMD command: /scripts/run.sh machine: prod-server owner: batuser start_times: "06:00" EOF fi jil < "$JIL_FILE"
The Atomicity Lie: Why job_defs Fail on Partial Changes
You think you're updating one field. You're actually overwriting the entire job definition. That's how autorepeat gets silently stripped when you only wanted to change the machine. Every time you run update_job, Autosys treats it as a wholesale replacement — fields you omit are reset to their defaults, not left untouched.
Proof of the wound: You push a script that updates command on a critical job. Next morning, alerting fails because alarm_if_fail is gone. You didn't delete it. Autosys did. Because your JIL didn't mention it.
The fix is brutal but simple: always pipe the current job definition through autorep -q, parse it, and inject only the changed attributes. Never hand-write an update_job from memory. Script it. Save yourself the 2am war room.
// io.thecodeforge — devops tutorial // Capture current state before update - name: Get existing job definition command: autorep -q PAYROLL_END_OF_DAY -J register: current_jil - name: Update only command and owner jil: job_name: PAYROLL_END_OF_DAY operation: update_job params: command: "/app/payroll/run_v2.sh" owner: "svc_payroll" # Preserve all other fields from current_jil.stdout description: "{{ current_jil.stdout | regex_findall('description: (.+)', '\1') | first }}" alarm_if_fail: "{{ current_jil.stdout | regex_findall('alarm_if_fail: (.+)', '\1') | first }}" # Repeat for every field your job uses
autorep -q output is your source of truth. If you're not capturing every field, you're gambling.The Cascade Problem: delete_job on a Box Job Will Nuke Your Dependency Chain
You remove a box job. Autosys doesn't warn you. It just deletes the box and every job inside it — no confirmation, no prompt, no undo. One command, forty-three jobs gone. The scheduler won't even tell your monitoring tools.
This isn't a bug. It's the design. Box jobs own their children. Delete the parent, the children die with it. No dependency tree validation. No 'are you sure?' flag.
The workaround is paranoid but fast: before you delete any box, dump its contents with autorep -B. Then delete jobs bottom-up. Children first. Then the box. If you bulk-delete with a script, add a dry-run mode that lists every job that will be removed. Make it print a count. Force a confirmation with a checksum — "type 'I_KNOW_47_JOBS_WILL_DIE' to continue."
Your production scheduler is not a playground. Treat every delete like a database drop.
// io.thecodeforge — devops tutorial // Dry-run delete with verification - name: List all jobs inside box PROD_BOX_DAILY command: autorep -B PROD_BOX_DAILY -q | grep 'job_name:' | awk '{print $2}' register: child_jobs - name: Count children set_fact: child_count: "{{ child_jobs.stdout_lines | length }}" - name: Prompt for confirmation pause: prompt: "WARNING: Deleting PROD_BOX_DAILY will remove {{ child_count }} jobs.\nType 'DELETE_{{ child_count }}_JOBS' to confirm." when: child_count | int > 0 - name: Delete children first (bottom-up) command: "sendevent -E FORCE_STARTJOB {{ item }}; sleep 1" loop: "{{ child_jobs.stdout_lines }}" when: delete_confirmed
autorep -B gives you the full tree. Use it.ACID Properties of SQL Transactions & Command Reference
JIL uses an embedded SQLite database, so every insert_job, update_job, or delete_job is an implicit SQL transaction. Understanding ACID—Atomicity, Consistency, Isolation, Durability—explains why partial job_defs fail silently. The BEGIN TRANSACTION command explicitly starts a multi-statement block, preventing partial writes. Use SAVEPOINT to mark a rollback point within a transaction. ROLLBACK TO SAVEPOINT undoes changes after that marker without aborting the whole transaction. RELEASE SAVEPOINT discards the marker without affecting data. These commands matter when scripting bulk job changes: a failed update in the middle won't corrupt 47 payroll jobs because you can roll back to a safe state before the batch. Without explicit transactions, Autosys treats each JIL statement independently, masking errors until job execution.
// io.thecodeforge — devops tutorial // SQL transaction commands for JIL safety BEGIN TRANSACTION; SAVEPOINT before_payroll_update; update_job: PAYROLL_BATCH condition: "s(MASTER_BOX)" -- Simulate failure: next command missing required box update_job: PAYROLL_CALC max_run_alarm: 300 ROLLBACK TO SAVEPOINT before_payroll_update; -- Safe state restored; no jobs corrupted RELEASE SAVEPOINT before_payroll_update; COMMIT;
Types of SQL Transactions & Optimization Strategies
JIL transactions fall into three types: implicit single-statement (default, one job per commit), explicit multi-statement (BEGIN/COMMIT block), and nested subtransactions (via SAVEPOINT). Implicit transactions are fast but dangerous for cascading changes like delete_job on a box. Explicit transactions allow atomic box deletes that roll back if any child job fails. Nested transactions help when updating dependency chains across multiple boxes. Optimization starts with minimizing transaction scope: commit small batches (5-10 jobs) rather than 500-job transactions to avoid table-level locks that stall the Autosys Event Processor. Use SAVEPOINT only when necessary—excessive savepoints bloat the transaction log. For bulk imports, disable triggers during the transaction (ALTER TABLE disables) then re-enable. Monitor job_def transactions in the $AUTOUSER/sqlite directory for disk I/O spikes. Batching with explicit transactions cut our job definition load time by 63%.
// io.thecodeforge — devops tutorial // Optimized bulk JIL transaction pattern BEGIN TRANSACTION; -- Batch 5 jobs per commit to reduce lock contention insert_job: EXPORT_DAILY job_type: c command: "/app/export.sh" insert_job: EXPORT_WEEKLY job_type: c command: "/app/weekly.sh" insert_job: EXPORT_MONTHLY job_type: c command: "/app/monthly.sh" insert_job: AGGREGATE_JOB condition: "s(EXPORT_DAILY)" insert_job: ARCHIVE_JOB condition: "s(AGGREGATE_JOB)" COMMIT; -- Next batch continues after brief pause
The Quiet Box Deletion That Killed a Payroll Batch
- Never use delete_box without a full autorep -q backup of the entire box tree.
- Always run
autorep -J boxname -q | grep job_namefirst to see what you're about to delete. - Consider renaming delete_box to something less lethal in your runbook — or just ban it in production.
autorep -J jobname to confirm. Use update_job instead. Never try to delete and re-insert — you'll lose history.autorep -J jobname -d. Running jobs ignore updates until next scheduled start. Also verify you spelled the attribute correctly.autorep -J %keyword% to search. Remember: case-sensitive. Also check global vs local instance.autorep -J jobname -q | grep -i 'job_type|machine|owner'jil < backup.jil (if backup exists) to compare working syntax.autorep -J jobname -d | head -5sendevent -E FORCE_STARTJOB -J jobname (if you want to clear a running state)ls -la /path/to/backups/*.jil 2>/dev/null || echo 'no backup found'autorep -J boxname -q (if box still partially exists) to reconstruct.| Subcommand | Creates? | Modifies? | Full replacement? | Deletes? |
|---|---|---|---|---|
| insert_job | Yes — new only | No — fails if exists | N/A | No |
| update_job | No — fails if not exists | Yes — partial update | No — only changed attrs | No |
| delete_job | No | No | No | Job only |
| delete_box | No | No | No | Box + all children |
| File | Command / Code | Purpose |
|---|---|---|
| insert_job.jil | insert_job: daily_reconcile | insert_job |
| update_job.jil | /* Change only the start time — everything else unchanged */ | update_job |
| delete_jobs.jil | /* Delete a single job */ | delete_job and delete_box |
| pitfall_examples.jil | /* WRONG: missing colon after job name */ | Common pitfalls when using JIL subcommands |
| automate_jil.sh | JOB_NAME="daily_reconcile" | Automating job lifecycle management with scripts |
| PartialUpdateFix.yml | - name: Get existing job definition | The Atomicity Lie |
| SafeBoxDelete.yml | - name: List all jobs inside box PROD_BOX_DAILY | The Cascade Problem |
| jil_acid_transactions.yml | BEGIN TRANSACTION; | ACID Properties of SQL Transactions & Command Reference |
| jil_transaction_optimization.yml | BEGIN TRANSACTION; | Types of SQL Transactions & Optimization Strategies |
Key takeaways
autorep -J jobname -q > backup.jil before making changesCommon mistakes to avoid
5 patternsUsing insert_job on an existing job
Using delete_box when you only want to remove the box container
Not backing up job definitions before delete operations
autorep -J jobname -q > backup.jil before any delete. Store backups in version control.Forgetting that update_job is partial — can't clear an attribute by omitting it
condition: "" or start_times: "".Assuming JIL syntax errors are obvious
autorep -J jobname -q after every JIL operation. Never trust the 'success' output alone.Interview Questions on This Topic
What is the difference between insert_job and update_job?
If you want to delete a box but keep its inner jobs, which command do you use?
How do you back up an AutoSys job definition before modifying it?
autorep -J jobname -q > backup.jil. This exports the complete JIL definition. You can later re-insert it with jil < backup.jil.Can you use update_job on a job that doesn't exist yet?
What happens to history when you delete an AutoSys job?
How do you handle a situation where an update_job doesn't seem to apply?
Frequently Asked Questions
No. insert_job will fail if a job with that name already exists. Use update_job to modify an existing job.
No. update_job is a partial update — you only specify the attributes you want to change. All other attributes keep their current values.
delete_job removes a single job. When used on a box, it removes only the box — the inner jobs become standalone. delete_box removes the box AND all inner jobs in one operation.
If you took a backup with autorep -J jobname -q > backup.jil before deleting, you can re-insert it with jil < backup.jil. Without a backup, the job definition is gone.
Not directly. AutoSys doesn't have a rename command. To rename a job, export the definition with autorep -q, modify the job name in the JIL file, insert the new version with insert_job, then delete the old one with delete_job.
The JIL parser will likely fail to parse the line, and the entire batch will abort with a syntax error. Always use the syntax attribute: value exactly.
Yes, you can pipe JIL commands directly to the jil command, e.g., echo "delete_job: oldjob" | jil. But it's safer to use a file for multi-line batches.
20+ years shipping production infrastructure and CI/CD at scale. Notes here come from systems that actually shipped.
That's AutoSys. Mark it forged?
3 min read · try the examples if you haven't