首页 技术 正文
技术 2022年11月23日
0 收藏 617 点赞 5,104 浏览 2391 个字

公司所用计划任务均是大概这样子的:

*/ * * * * root cd /opt/xxxx/test_S1/html/xxxx/admin; php index.php task testOne >/dev/null >&
*/ * * * * root cd /opt/xxxx/test_S1/html/xxxx/admin; php index.php task testTwo >/dev/null >&

可以看到把输出与标准错误进行重定向到空设备了,这样做是有一定原因的。查阅了一些资料,在这里描述一下:

1.ssh登陆服务器
2.新建一个php文件test.php,代码如下:

<?php
sleep();
echo "aaa\n";
file_put_contents("/tmp/test.txt",time());
?>

3.用以下命令执行test.php程序

$ php test.php &

查看 /tmp/test.txt 文件的内容为1497613738

4.然后再次执行如下命令。命令执行后,马上使用exit命令退出登陆

$ php test.php &

5 然后ssh登陆服务器,发现/tmp/test.txt 文件的内容依然是 1497613738。说明第二次执行test.php时,file_put_contents函数没有执行,或者没有执行成功。

6 使用strace进行追踪:

正常情况下的追踪:
strace -p 1475
结果:
Process  attached
restart_syscall(<... resuming interrupted call ...>) =
write(, "aaa\n", 4aaa
) =
lstat("/tmp/test.txt", 0x7ffe792ebe90) = - ENOENT (No such file or directory)
lstat("/tmp", {st_mode=S_IFDIR|S_ISVTX|, st_size=, ...}) =
open("/tmp/test.txt", O_WRONLY|O_CREAT|O_TRUNC, ) =
fstat(, {st_mode=S_IFREG|, st_size=, ...}) =
lseek(, , SEEK_CUR) =
write(, "", ) =
close() =
munmap(0x7f4840239000, ) =
close() =
close() =
munmap(0x7f4847510000, ) =
close() =
munmap(0x7f4847511000, ) =
sched_getaffinity(, , {ffffff, , , , , , , , , , , , , , , }) =
sched_setaffinity(, , {ffffff, , , , , , , , , , , , , , , }) =
munmap(0x7f48404c8000, ) =
munmap(0x7f48406ce000, ) =
munmap(0x7f4840b39000, ) =
munmap(0x7f484090b000, ) =
munmap(0x7f4840d49000, ) =
exit_group() = ?
+++ exited with +++
[]+ Done php test.php

退出后再登陆的追踪:

strace -p 3881

restart_syscall(<... resuming interrupted call ...>) =
write(, "aaa\n", ) = - EIO (Input/output error)
munmap(0x7f6b7fc04000, ) =
close() =
close() =
munmap(0x7f6b86edb000, ) =
close() =
munmap(0x7f6b86edc000, ) =
sched_getaffinity(, , {ffffff, , , , , , , , , , , , , , , }) =
sched_setaffinity(, , {ffffff, , , , , , , , , , , , , , , }) =
munmap(0x7f6b7fe93000, ) =
munmap(0x7f6b80099000, ) =
munmap(0x7f6b80504000, ) =
munmap(0x7f6b802d6000, ) =
munmap(0x7f6b80714000, ) =
exit_group() = ?
+++ exited with +++

通过对比可以看到echo处出现了 输入/输出错误,最终没有执行file_put_contents函数。

7 原因:

为什么退出登陆后,再登陆,就会发生EIO错误呢?这个和linux的会话处理有关。
当用户ssh登陆一个服务器时,也就开始了一个会话。会话开始后,标准输入(stdin)、标准输出(stdout)、标准错误(stderr)会连接到一个对应的终端(pty)。
用户登陆后,任何标准输出都会在终端中有反应。标准输出的文件句柄是1。因此,php中的echo(“aaa\n”) 会导致执行系统调用write(1, “aaa\n”, 4). 会在终端中写aaa\n。
​当用户退出登陆时,一个会话就结束了。会话结束时,修改所有打开该终端的文件句柄,改成不可读也不可写;
​用户退出登陆后再执行write(1, “aaa\n”, 4),会报EIO错误。因为终端句柄已经不可写。EIO错误发生后,导致进程结束。

解决办法
方法一:
​使用重定向符号&把标准输出重定向到空洞。

$ php test.php > /dev/null  >& &   这里的& 可以用也可以不用

方法二:
使用nohup。

$ nohup php test.php &

说明:

如果你正在运行一个进程,而且你觉得在退出帐户时该进程还不会结束,那么可以使用nohup命令。

该命令可以在你退出帐户/关闭终端之后继续运行相应的进程。nohup就是不挂起的意思( n ohang up)。

而我们公司采用的是第一种方法,关于对/dev/null 2 >&1 & 的描述,看另外一篇文章http://www.cnblogs.com/zhenghongxin/p/7029173.html

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,958
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,482
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,328
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,111
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,743
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,777