Ubuntu’s Rust Test: Will the Old Scripts Still Run?
Key takeaways
- uutils is a Rust implementation of coreutils that aims for GNU compatibility.
- Rust’s memory safety does not guarantee correct command behavior.
- Compatibility includes output formatting, exit codes, file permissions, and symbolic links.
- Performance comparisons need matching workloads, options, and correct results.
The toughest test for a Rust rewrite of Ubuntu’s basic commands may be a shell script nobody has touched in years. If Ubuntu 26.10 switches those tools to Rust implementations, familiar commands such as cp and ls would need to keep working across everything from an interactive terminal to a server deployment. The question is simple: will yesterday’s script still work tomorrow?
A familiar command hides a large contract
Copy a file with cp, list a directory with ls, or arrange text with sort: these are everyday encounters with coreutils. GNU coreutils is the widely used implementation. uutils implements these tools in Rust, with GNU compatibility as its goal.
That goal reaches well beyond keeping the command names.
A replacement must understand the options existing scripts pass to it. It must also produce the expected results under the same conditions. Even output formatting can matter: another program may depend on particular spaces or line breaks.
A person can usually work around a slightly different display. A deployment script is rarely so accommodating.
The longer a utility has been around, the more opportunities other software has had to depend on its details. Those details become part of the compatibility contract, whether anyone intended them to or not.
Memory safety solves a specific problem
One reason to choose Rust is memory safety. Safe Rust uses compile-time checks and runtime checks to prevent classes of errors such as accessing invalid memory or using memory after it has been freed.
Code involving unsafe, and boundaries with external libraries, still need separate scrutiny.
That protection matters. But it does not establish that a file utility does the right thing.
A memory-safe program can still delete the wrong file. It can assign incorrect permissions or make the wrong decision about overwriting an existing destination. These are logic errors: the program handles memory safely while carrying out the wrong operation.
The case for Rust therefore needs two kinds of evidence. One concerns the defects the language helps prevent. The other concerns whether the replacement preserves the behavior people depend on.
Failure behavior is part of compatibility
Successfully copying one file proves very little about a cp replacement.
What happens when the user lacks permission? When the destination already exists? When the disk fills up halfway through?
Scripts often make their next decision using an exit code, the numeric result a command returns. Generally, 0 means success. A different result can determine whether the script continues or stops.
Partial failure makes this more complicated. If a command processes some files and then fails, both the work already completed and the final exit code matter. Differences in either can change what happens next.
File attributes belong in the same conversation. A command such as cp -p needs testing for preserved permissions and timestamps, alongside file contents. Symbolic links need attention too: operating on a link itself can produce a different result from operating on the file it points to.
A useful compatibility test suite therefore includes successful operations, invalid inputs, and failure conditions. Tests from the existing implementation provide a foundation. The scripts distributions and users actually run provide another essential check.
Benchmark the job, not the language
Rust does not automatically make a command faster. Both Rust and C can compile to efficient machine code. Algorithms, memory management, and use of operating-system facilities all affect the result.
Even the same command can face very different bottlenecks.
Copying one large file may depend heavily on storage speed. Copying thousands of small files can put more weight on the cost of opening files and checking their attributes.
For sort, input size, sorting strategy, and memory use matter. So do locale settings, which govern language-specific ordering rules. Comparisons need to account for those rules.
A fair benchmark uses the same hardware, input, and options. It checks correctness first, then measures execution time and memory use. Finishing faster because required behavior is missing does not demonstrate a faster equivalent tool.
For Ubuntu, a convincing transition would pair stronger memory safety with evidence that existing scripts still behave as expected. The success criterion is fewer defects and familiar results, including when commands fail. An old deployment script finishing uneventfully would be a useful result.
Comments
Loading comments...