I cannot find anything resembling file locking like some programs use in Linux to prevent multiple instances from running. In Python, I'd use pylockfile.
Am I overlooking similar functionality in Rust, or should I just implement it from scratch?
For contemporary Rust (1.8+) you should use the fs2
crate. It is a cross-platform library that provides some file system functions not found in the standard library, including file locking.
fs2
's file locking functions internally use flock(2)
on UNIX and LockFileEx
on Windows.
Example:
//! This program tries to lock a file, sleeps for N seconds, and then unlocks the file.
// cargo-deps: fs2
extern crate fs2;
use fs2::FileExt;
use std::io::Result;
use std::env::args;
use std::fs::File;
use std::time::Duration;
use std::thread::sleep;
fn main() {
run().unwrap();
}
fn run() -> Result<()> {
let sleep_seconds = args().nth(1).and_then(|arg| arg.parse().ok()).unwrap_or(0);
let sleep_duration = Duration::from_secs(sleep_seconds);
let file = File::open("file.lock")?;
println!("{}: Preparing to lock file.", sleep_seconds);
file.lock_exclusive()?; // block until this process can lock the file
println!("{}: Obtained lock.", sleep_seconds);
sleep(sleep_duration);
println!("{}: Sleep completed", sleep_seconds);
file.unlock()?;
println!("{}: Released lock, returning", sleep_seconds);
Ok(())
}
We can see that the two processes are sequenced waiting on the file lock.
$ ./a 4 & ./a 1
[1] 14894
4: Preparing to lock file.
4: Obtained lock.
1: Preparing to lock file.
4: Sleep completed
4: Released lock, returning
1: Obtained lock.
1: Sleep completed
1: Released lock, returning
[1]+ Done ./a 4