Rust became popular for one key reason: it made memory safety a core principle. In a world where a small mistake like a segmentation fault or a race condition can crash an applicationāor worse, open it up to serious vulnerabilitiesāRust stepped up and said: āNo more.ā
But what about us? Those of us who write shell scripts every day to automate DevOps tasks, manage CI/CD pipelines, handle data, files, and processes? Do we have any tools that help us write "memory-safe" shell code?
Not quite like Rust. But we do have a few tools to make things better. One of the most underrated? The local
keyword.
š”ļø Why local
Is Important
In Bash, when you define variables inside a function, those variables are global by default. This means that your function can accidentally change the global environment even after it finishes.
Hereās a simple example:
#!/bin/bash
foo() {
var="modified"
}
var="original"
foo
echo "$var" # -> prints "modified"
The function foo
unexpectedly changed the global variable var
. This can lead to hard-to-debug issues, especially in larger scripts or CI/CD environments with many functions.
š Use local
to Contain State
The local
keyword solves this problem by making a variable local to the function scope:
foo() {
local var="modified"
}
var="original"
foo
echo "$var" # -> prints "original"
Just like Rust ensures memory isolation and ownership, local
helps isolate variable state and prevent cross-function contamination.
ā ļø But Be Careful How You Use local
A very common mistake is doing this:
myfunc() {
local myvar=$(some_command)
}
This is not safe. If some_command
fails, behaves unexpectedly, or produces weird output, it may interfere with the local
declaration.
Also, ShellCheck (an amazing Bash linter) warns against this with:
SC2155: Declare and assign separately to avoid masking return values.
The correct, safe way is:
myfunc() {
local myvar
myvar=$(some_command)
}
This separates the declaration (local myvar
) from the assignment (myvar=$(...)
), avoiding unintended behavior.
š§Ŗ Practical Example
Letās say you want a function that returns the size of a file in bytes:
get_file_size() {
local size
size=$(stat -c%s "$1")
echo "$size"
}
file="example.txt"
echo "Size: $(get_file_size "$file") bytes"
In this example:
-
size
is local and wonāt affect other parts of the script - The function is safe and reusable
- You avoid unexpected side effects
š Final Thoughts
No, local
isnāt Rust. But in the world of shell scripting, itās one of the best tools we have for writing modular, safe, and maintainable code. Using it correctly helps prevent bugs and makes your scripts more robust and predictable.
If you're writing scripts for DevOps, CI/CD, or system automation, make local
your default when working with function variables. Itās a small habit that brings huge value.
š¬ Do you know other tips or patterns for writing safer, cleaner shell scripts? Share them in the comments! The more we exchange ideas, the stronger our scripting practices become.
Top comments (0)