実行後に消えるバイナリを作る

ネタを募集していたら

This executable will self destruct in five secondsを様々な方法で実現してみる

というアイデアをrand0mから頂いたので、やります。

構想

まぁ多分/proc/self/exeを読んでremoveすれば良いんじゃないかなと思う。

Lockとか面倒なので、別プロセスでやればいいかな

実装

とりあえずシンプルに思いつく実装

use std::{env, thread, time::Duration, process::Command};

pub struct ThisExecutableWillSelfDestruct
{
    seconds: Duration,
}

impl ThisExecutableWillSelfDestruct 
{
    pub fn new(seconds: Duration) -> Self
    {
        Self {
            seconds,
        }
    }

    pub fn fire(self) {
        let ThisExecutableWillSelfDestruct { seconds } = self;
        thread::sleep(seconds);

        let delete_handle = thread::spawn(move || {
            let exe = env::current_exe().expect("Failed to get current executable");

            if cfg!(target_os = "windows") {
                let mut cmd = Command::new("cmd");
                cmd.args(&["/C", "del", exe.to_str().unwrap()]);
                if let Err(e) = cmd.spawn() {
                    eprintln!("Failed to spawn delete process: {}", e);
                }
            } else {
                let mut cmd = Command::new("sh");
                cmd.args(&["-c", &format!("rm {}", exe.to_str().unwrap())]);
                if let Err(e) = cmd.spawn() {
                    eprintln!("Failed to spawn delete process: {}", e);
                }
            }
        });

        let _ = delete_handle.join();
    }
}

spawnさせたthreadに死なれると困るのでjoinしている。あとせっかくなのでWindows対応もしている。Windows無いので動作確認できないけど。

用法はこんな感じだろうか

use this_executable_will_self_destruct::ThisExecutableWillSelfDestruct;
use std::time::Duration;

fn main() {
    println!("This executable will self-destruct in five seconds");
    ThisExecutableWillSelfDestruct::new(Duration::from_secs(5)).fire();
}
$ cargo build --examples
   Compiling this_executable_will_self_destruct v0.1.0 (/home/lilium/src/github.com/n01e0/this_executable_will_self_destruct)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.29s
$ ./target/debug/examples/letter
This executable will self-destruct in five seconds
$ stat ./target/debug/examples/letter
stat: cannot statx './target/debug/examples/letter': No such file or directory

いい感じ。

this_executable_will_self_destruct

crateもpublishした。

今後

DestructorとしてFnOnceを渡せるようにしても良いかもしれない。あとはDropでの実装とか。

終わりに

この記事はn01e0 Advent Calendar 2024の25日目の記事とします。

やっと終わらせる事ができて安心です。