公司所用計劃任務都是大概這樣子的:
*/2 * * * * root cd /opt/xxxx/test_S1/html/xxxx/admin; php index.php task testOne >/dev/null 2>&1*/2 * * * * root cd /opt/xxxx/test_S1/html/xxxx/admin; php index.php task testTwo >/dev/null 2>&1
可以看到把輸出與標準錯誤進行重定向到空設備了,這樣做是有一定原因的。查閱了一些資料,在這裡描述一下:
1.ssh登陸伺服器<br>2.新建一個php檔案test.php,程式碼如下:
<?php sleep(50); 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
Process 1475 attached restart_syscall(<... resuming interrupted call ...>) = 0write(1, "aaa\n", 4aaa ) = 4lstat("/tmp/test.txt", 0x7ffe792ebe90) = -1 ENOENT (No such file or directory) lstat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=65536, ...}) = 0open("/tmp/test.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3fstat(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0lseek(3, 0, SEEK_CUR) = 0write(3, "1497614186", 10) = 10close(3) = 0munmap(0x7f4840239000, 528384) = 0close(2) = 0close(1) = 0munmap(0x7f4847510000, 4096) = 0close(0) = 0munmap(0x7f4847511000, 4096) = 0sched_getaffinity(1475, 128, {ffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) = 128sched_setaffinity(0, 128, {ffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) = 0munmap(0x7f48404c8000, 2119936) = 0munmap(0x7f48406ce000, 2345056) = 0munmap(0x7f4840b39000, 2162536) = 0munmap(0x7f484090b000, 2282472) = 0munmap(0x7f4840d49000, 323584) = 0exit_group(0) = ? +++ exited with 0 +++[1]+ Done php test.php
<br>
退出後再登陸的追蹤:
strace -p 3881
restart_syscall(<... resuming interrupted call ...>) = 0write(1, "aaa\n", 4) = -1 EIO (Input/output error) munmap(0x7f6b7fc04000, 528384) = 0close(2) = 0close(1) = 0munmap(0x7f6b86edb000, 4096) = 0close(0) = 0munmap(0x7f6b86edc000, 4096) = 0sched_getaffinity(3881, 128, {ffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) = 128sched_setaffinity(0, 128, {ffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) = 0munmap(0x7f6b7fe93000, 2119936) = 0munmap(0x7f6b80099000, 2345056) = 0munmap(0x7f6b80504000, 2162536) = 0munmap(0x7f6b802d6000, 2282472) = 0munmap(0x7f6b80714000, 323584) = 0exit_group(0) = ? +++ exited with 0 +++
透過對比可以看到echo處出現了輸入/輸出錯誤,最後沒有執行file_put_contents函數。
7 原因:
為什麼退出登陸後,再登陸,就會發生EIO錯誤?這個和linux的會話處理有關。 <br>當使用者ssh登陸一個伺服器時,也就開始了一個會話。會話開始後,標準輸入(stdin)、標準輸出(stdout)、標準誤差(stderr)會連接到對應的終端(pty)。 <br>使用者登陸後,任何標準輸出都會在終端機中有反應。標準輸出的文件句柄是1。因此,php中的echo("aaa\n") 會導致執行系統呼叫write(1, "aaa\n", 4). 會在終端機中寫aaa\n。 <br>當使用者退出登陸時,一個會話就結束了。會話結束時,修改所有開啟該終端機的檔案句柄,改成不可讀也不可寫;<br>使用者退出登陸後再執行write(1, "aaa\n", 4),會報EIO錯誤。因為終端句柄已經不可寫。 EIO錯誤發生後,導致進程結束。
解決方法<br>方法一:<br>使用重定向符號&把標準輸出重定向到空洞。
$ php test.php > /dev/null 2 >&1 & 这里的& 可以用也可以不用
方法二:<br>使用nohup。
$ nohup php test.php &
說明:
# 如果你正在執行一個進程,而且你覺得在退出帳戶時該進程還不會結束,那麼可以使用nohup指令。
該指令可以在你退出帳戶/關閉終端機之後繼續執行對應的進程。 nohup就是不掛起的意思( n ohang up)。
而我們公司採用的是第一種方法,關於對/dev/null 2 >&1 & 的描述,看另外一篇文章
以上是PHP關於排程任務的實例的詳細內容。更多資訊請關注PHP中文網其他相關文章!