10 Simple Bash Scripts to Automate Your DevOps Workflow
A collection of 10 small yet useful Bash scripts for DevOps: backup, tmp cleanup, disk monitoring, service restart, batch rename, log rotation, archive compression, SSL checks, bulk ping, and folder sync.
Why collect small scripts?
In the Bash series, we went from variables, conditionals, and loops to error handling, cron, and best practices. But the real value of Bash lies in the small scripts that run every day: nightly backups, cleaning full disks, restarting a crashed service at 2 AM.
This post collects 10 lightweight scripts with a true DevOps flavor. Each script is under 30 lines, follows set -euo pipefail, quotes variables properly, and can be plugged into cron right away. The outline is inspired by community ideas and rewritten from scratch to match this series’ standards.
Dated folder backup
The most basic need: back up a config or data folder every night.
| |
Explanation:
tar -czfpacks a whole folder into a single file that is easy to copy elsewhere.-Ccombined withdirname/basenameavoids storing absolute paths inside the archive.find -mtimecleans up old backups automatically — the classic mistake is backing up without ever cleaning up until the disk fills.- Taking
SOURCE_DIRas a parameter instead of hardcoding makes the script reusable for many apps.
Clean temp files and old caches
A bloated /tmp folder or cache directory is a common cause of full disks.
| |
Explanation:
find -mtime +7 -deleteonly removes old files and leaves recently used ones alone.-printbefore-deletelogs what was removed for easy auditing.- Checking
-dbefore deleting guards against typos pointing at the wrong folder. - Dry-run with
-printinstead of-deletefirst when testing on production.
Disk usage monitoring
A compact version of the monitoring script from the monitoring post: check usage and alert past a threshold.
| |
Explanation:
df --output=pcentselects exactly the percentage column, more stable than parsing defaultdfoutput.tr -dc '0-9'strips the number out of a string like82%.- Exit code
1past the threshold lets cron or a pipeline detect the failure. - Run it via cron every 30 minutes, or trigger a webhook when the exit code is non-zero.
Auto-restart a crashed service
The classic on-call scenario: a service stops and nobody notices.
| |
Explanation:
systemctl is-active --quietchecks status via exit code, no text parsing needed.- Always verify again after a few seconds instead of assuming the restart worked.
- Schedule it in cron every 5 minutes for critical services, with logs to a file for tracing.
- For many servers, wrap it in an SSH loop as shown in the SSH post.
Batch file rename
During deploys or log rotation, you often need to rename many files by pattern.
| |
Explanation:
nullglobmakes an unmatched glob expand to nothing instead of the raw pattern string.- Quoting
"${files[@]}"correctly handles filenames with spaces. mv --prevents filenames starting with-from being treated as options.- A date suffix makes sorting and searching easy.
Manual log rotation
Before relying on system logrotate, understanding the rotation mechanism in Bash makes debugging easier.
| |
Explanation:
du -mreports size in MB for threshold comparison.- The reverse loop keeps at most
KEEP_FILEScopies, the oldest one gets overwritten. touchrecreates the log file immediately so the app does not keep writing to the moved file.- For apps that log continuously, send a reload signal after rotation.
Compress old log archives
After rotating logs, compress the old copies to save disk space.
| |
Explanation:
! -name "*.gz"avoids compressing files twice.-print0withread -d ''safely handles filenames with spaces or special characters.gzip -9uses maximum compression, ideal for text logs.- Run weekly via cron, right after the rotation step.
Check SSL certificate expiry
An expired certificate you forgot to renew is one of the most avoidable incidents.
| |
Explanation:
openssl s_client -connectfetches the real certificate chain from the running server.-servername(SNI) is required when one IP serves multiple domains.- Converting the expiry date to epoch time gives an exact days-remaining count.
- Distinct exit codes for
WARNINGvsCRITICALlet the alerting system route correctly.
Bulk host ping check
When managing many servers, you need a quick way to see which hosts are alive.
| |
Sample hosts.txt:
| |
Explanation:
ping -c 2 -W 2sends 2 packets with a 2-second timeout each — fast enough for dozens of hosts.- Reading the file line by line with
while readskips#comments so you can document inline. || [[ -n "$host" ]]handles a final line missing its newline.- Next upgrade: run checks in parallel with
&andwaitas in the parallel post.
Sync folders with rsync
Copying folders between machines or doing incremental backups is much faster with rsync than cp.
| |
Explanation:
-apreserves permissions, ownership, and timestamps;-zcompresses on the wire;-vgives detailed logs.--deletesyncs deletions — files removed at the source are removed at the destination, keeping both sides identical.--excludeskips caches and temp files, cutting volume significantly.- The trailing
/onSOURCE_DIRmatters in rsync: with/it copies the contents, without it copies the folder itself.
How to run and schedule
Make executable and test
| |
Plug into cron
| |
The cron notes analyzed in the cron post still apply: always use absolute paths, declare PATH and environment variables explicitly, and redirect both stdout and stderr to a log.
Deployment notes
- Never hardcode secrets: Every script above takes parameters or environment variables. Do not embed passwords, tokens, or webhook URLs in files. Use a
chmod 600.envfile andsourceit when needed. - Always quote variables:
"$SOURCE_DIR","${files[@]}"— the rule from the best practices post. Small scripts invite overconfidence, and unquoted variables break on filenames with spaces. - Fail fast, report clearly: Use
set -euo pipefail, validate input at the top, and return meaningful exit codes so cron and pipelines can detect failures. A script that finishes silently did not necessarily run correctly. - Dry-run first on production: For destructive scripts (
cleanup,find -delete) and sync (rsync --delete), first run with-printor--dry-run, confirm the file list, then allow real deletion. - One script, one job: Each file above does exactly one task. When you need a multi-step chain, write an orchestrator that calls each child script instead of stuffing everything into one long, untestable file.
- Lint before committing: Run
shellcheckandbash -non all 10 scripts. Add them to pre-commit or CI so the team keeps one standard.
Conclusion
None of the ten scripts above are fancy — backup, tmp cleanup, disk check, service restart, rename, log rotation, archive compression, SSL check, host ping, folder sync. Together, though, they save hours of manual work every week and directly reduce overnight incidents.
Start with a single script: pick your team’s biggest pain point today, deploy that script via cron, observe it for a week, then add the next one. Once the small scripts are stable, you have a solid foundation to move toward Bash in CI/CD and centralized monitoring.
Do not leave automation on paper — run your first script today.
