最近发现很多同学不知道线上操作替换文件的要点。所以又整理了一下。


    线上替换一个正在运行进程的文件时(包括二进制、动态库、需要读取的资源文件等)。应避免使用cp/scp操作。而需要使用mv/rsync作为替代。

    原因:cp是将源文件截断然后写入新内容。也就是说正在打开这个文件的进程可以立刻感知到修改。修改文件内容很可能导致程序逻辑错误甚至崩溃。而mv则是标记”删除“老文件,然后放一个新的同名文件过去。也就是说老文件和新文件其实是两个不同文件(inode不同),只是名字一样而已。正在打开老文件的进程不会受到影响。如果进程使用了mmap打开某文件(比如载入so),如果目标文件被使用cp覆盖并且长度变小。那么读取差额部分的地址时(在新文件中其实已经不存在了),会导致SIGBUS信号。使进程崩溃。




    至于可执行文件本身。倒是不怕cp导致崩溃。。因为cp时会报”text file busy"。压根cp不了。这时候也应该使用mv类操作。替换完成后重启进程。执行的就是新的可执行文件了。





Tags:
    lighttpd有一个功能,就是收到SIGHUP信号时会重新打开日志文件。这样在日志切分时很有用。但最近发现了一个bug。

    就是如果有子进程挂掉。父进程新fork出的子进程accesslog会默认打日志到最最开始父进程启动时的那个文件里。


   看了下代码。原来父进程在收到SIGHUP的时候只是把errorlog重新打开了下。没有重新打开accesslog(没办法,这个句柄是mod_accesslog模块搞的)。所以父进程维护的accesslog句柄一直是最老的。它本身不打accesslog日志倒无所谓。但它fork出的子进程是打的。这样就有问题了。



    一个最简单方法。就是外部脚本判断进程有更新的时候发一个SIGHUP信号过去。

    根治方法就是父进程重新启动子进程时给其发一个SIGHUP信号。

    至于父进程自己处理SIGHUP时重新打开句柄这个我感觉不太好。毕竟那是模块内部数据。lighttpd主干不应该关心。





Tags: ,
分页: 1/1 第一页 1 最后页 [ 显示模式: 摘要 | 列表 ]