如何写一个自我replace/更新二进制文件?

我正在尝试编写一个C程序,它可能会查找一个url,并将其新版本,它是可用的,它应该能够更新自己。

我试过的方法是:

  1. 叉出一个新的过程来下载新的二进制说BINARY.tmp,我正在使用的代码是叉:

    int forkout_cmd(char *cmdstr) { pid_t pid; char *cmd[4]; cmd[0] = "/bin/bash"; cmd[1] = "-c"; cmd[2] = cmdstr; cmd[3] = NULL; pid = vfork(); if( pid == -1 ) { logmsg("Forking for upgradation failed."); return -1; }else if( pid == 0 ){ /* we are in child process */ execvp(cmd[0], cmd); logmsg("execl failed while executing upgradation job."); }else{ /* need not to wait for the child to complete. */ wait(NULL); } return 0; } 
  2. 新进程尝试覆盖原始的BINARY

    例如你可以考虑分叉的例程可能是:

     forkout_cmd("wget -O BINARY.tmp https://someurl.com/BINARY_LATEST; /bin/mv -f BINARY.tmp BINARY"); 

但是,由于原来的二进制文件仍然在执行中,所以覆盖失败,因此在磁盘上繁忙,有人可以提供一些build议来解决这个问题。

提前致谢。

重命名当前正在运行的二进制文件,写入新的二进制文件,运行它,然后再删除重命名的二进制文件。

我将binary.tmp保存到与可执行文件相同的目录中,验证它的校验和/签名(无论100%确保没有错误发生),然后将其原始地重命名为可执行文件的名称。

在Linux下,这可以在程序运行的时候完成,没有任何问题(你只是改变链接,底层文件在映射打开的时候仍然存在,直到程序关闭或者重新启动)。

我会在任何情况下重命名原始文件,甚至覆盖它。 这是不安全的,没有必要。 在触摸原始文件之前,您可以执行临时文件上可能会失败的所有“不安全”操作。 如果在原子重命名中出现任何问题,您仍然有工作原件。

然后提示用户重新启动程序(如果交互)并完成。