PHP 不等待 exec() 在我想要的时候完成
PHP not waiting for exec() to finish when I want it to
我正在 运行 为 Raspberry Pi 上的数据记录工具设置 Web 界面。 PHP5.
用户按下按钮调用 PHP 脚本到 运行 进程(使用 exec),然后 return 结果文件。无论出于何种原因,exec() 函数不会等待完成,并且脚本失败,因为它正在寻找的文件尚未创建。
当我用 print 等简单脚本替换脚本时,等待 5 秒,print - 然后它会等待 exec() 完成。唯一的区别在于我调用的 python 脚本。有谁知道可能导致这种情况的原因吗?
PHP 脚本:
<?php
$file = "/var/tmp/logs/FaultLog.csv";
exec("python /data/scripts/test.py", $output, $return);
if (!file_exists($file)) {
die ("Error: Fault log could not be created.");
}
$type = filetype($file);
// Send file headers
header("Content-type: $type");
header("Content-Disposition: attachment;filename=FaultLog.csv");
header("Content-Transfer-Encoding: binary");
header('Pragma: no-cache');
header('Expires: 0');
// Send the file contents.
set_time_limit(0);
readfile($file);
?>
Python 有效的脚本:
import time
print "hello"
time.sleep(5)
print "goodbye"
Python 脚本无效。它很长,但为了以防万一,我决定把它全部包括在内。
#!/usr/bin/env python
import sqlite3, subprocess, re, os
faultID = hours = minutes = 0
csv_path = "/var/tmp/logs/"
db_path = "/data/databases/FaultDictionary.db"
def parse_msg (line):
global faultID, hours, minutes
if (" 12 41 01 " in line): #single message
#parse CAN data
try:
data = line.split(" ")[4][12:17].replace(" ","")
faultID = int(data[2:] + data[:2], 16)
except:
return "Error: Unable to parse data. Data: " + line
elif (" 12 41 02 " in line): #single message
#parse CAN data
try:
data = line.split(" ")[4][12:17].replace(" ","")
hours = int(data[2:] + data[:2], 16)
except:
return "Error: Unable to parse data. Data: " + line
elif (" 12 41 03 " in line): #single message
#parse CAN data
try:
minutes = int(line.split(" ")[4][12:14], 16)
except:
return "Error: Unable to parse data. Data: " + line
elif ("581 [8] 80" in line): #crashed
return "Error: Crashed motor controller. Please try again."
else:
return "Error: Unexpected message format, cannot decode reply from motor controller. Data: " + line
return ""
conn = sqlite3.connect(db_path)
curs = conn.cursor()
#note time
p = subprocess.Popen("date +\"%Y-%m-%d %H:%M\"", stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
current_date = output
#Create needed folder structure
if not (os.path.exists(csv_path)):
os.makedirs(csv_path)
csv_path += "FaultLog.csv"
with open(csv_path, 'w+') as file:
file.write("Date:," + current_date[:10] + "\n")
file.write("Time:," + current_date[11:] + "\n\n")
#SEVCON Fault Retreival
file.write('Hours Ago [h], Minutes & Seconds Ago, Fault ID, Fault Name, Fault Cause, Fault Remedy\n')
#send password to gain access
p = subprocess.Popen("cansend can0 601#2B005002DF4BEFFA", cwd="/data/can-utils/", stdout=subprocess.PIPE, shell=True)
p = subprocess.Popen("candump -t A -n 1 -T 100 can0,581:7ff", cwd="/data/can-utils/", stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
for num in range(0,40):
pass
#select event through 4111
p = subprocess.Popen("cansend can0 601#2B114100" + hex(num)[2:].zfill(2) + "00EFFA", cwd="/data/can-utils/", stdout=subprocess.PIPE, shell=True)
p = subprocess.Popen("candump -t A -n 1 -T 100 can0,581:7ff", cwd="/data/can-utils/", stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
#send request for event ID through 4112
p = subprocess.Popen("(sleep 0.1; cansend can0 601#4012410100000000; cansend can0 601#4012410200000000; cansend can0 601#4012410300000000;) &", cwd="/data/can-utils/", stdout=subprocess.PIPE, shell=True)
p = subprocess.Popen("candump -t A -n 3 -T 500 can0,581:7ff", cwd="/data/can-utils/", stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
message = ""
if len(output) > 0: # got the response message
lines = output.strip().split("\n")
for line in lines:
message = parse_msg(line)
else:
message = "Error: Did not receive reply from motor controller."
if message == "":
#query database for fault description and remedy
curs.execute("SELECT * FROM FaultDictionary WHERE faultID = '" + str(faultID) + "'") #faultID, message, description, action
for row in curs: #only ever one, since unique
#record to csv
file.write(str(hours) + "," + str(minutes) + "," + str(row[0]) + "," + str(row[1]) + "," + str(row[2]) + "," + str(row[3]) + "\n")
#print str(hours) + "," + str(minutes) + "," + str(row[0]) + "," + str(row[1]) + "," + str(row[2]) + "," + str(row[3]) + "\n"
else:
print message
break
#BMS Fault Retrieval
#file.write('\n\nFault ID\n')
if not message == "":
os.remove(csv_path)
conn.close()
tldr; PHP exec() 函数调用 python 脚本。 Exec() 应该等待您调用的任何内容完成。对某些脚本这样做,但对其他脚本不这样做。
Exec 是一个同步阻塞调用,当没有 &
传递给参数时强制程序/执行在后台发生。
这让我相信处理请求的 Apache
实例的所有者没有执行 Python
脚本的权限。
您应该相应地调整脚本或 Apache 用户的权限。
我正在 运行 为 Raspberry Pi 上的数据记录工具设置 Web 界面。 PHP5.
用户按下按钮调用 PHP 脚本到 运行 进程(使用 exec),然后 return 结果文件。无论出于何种原因,exec() 函数不会等待完成,并且脚本失败,因为它正在寻找的文件尚未创建。
当我用 print 等简单脚本替换脚本时,等待 5 秒,print - 然后它会等待 exec() 完成。唯一的区别在于我调用的 python 脚本。有谁知道可能导致这种情况的原因吗?
PHP 脚本:
<?php
$file = "/var/tmp/logs/FaultLog.csv";
exec("python /data/scripts/test.py", $output, $return);
if (!file_exists($file)) {
die ("Error: Fault log could not be created.");
}
$type = filetype($file);
// Send file headers
header("Content-type: $type");
header("Content-Disposition: attachment;filename=FaultLog.csv");
header("Content-Transfer-Encoding: binary");
header('Pragma: no-cache');
header('Expires: 0');
// Send the file contents.
set_time_limit(0);
readfile($file);
?>
Python 有效的脚本:
import time
print "hello"
time.sleep(5)
print "goodbye"
Python 脚本无效。它很长,但为了以防万一,我决定把它全部包括在内。
#!/usr/bin/env python
import sqlite3, subprocess, re, os
faultID = hours = minutes = 0
csv_path = "/var/tmp/logs/"
db_path = "/data/databases/FaultDictionary.db"
def parse_msg (line):
global faultID, hours, minutes
if (" 12 41 01 " in line): #single message
#parse CAN data
try:
data = line.split(" ")[4][12:17].replace(" ","")
faultID = int(data[2:] + data[:2], 16)
except:
return "Error: Unable to parse data. Data: " + line
elif (" 12 41 02 " in line): #single message
#parse CAN data
try:
data = line.split(" ")[4][12:17].replace(" ","")
hours = int(data[2:] + data[:2], 16)
except:
return "Error: Unable to parse data. Data: " + line
elif (" 12 41 03 " in line): #single message
#parse CAN data
try:
minutes = int(line.split(" ")[4][12:14], 16)
except:
return "Error: Unable to parse data. Data: " + line
elif ("581 [8] 80" in line): #crashed
return "Error: Crashed motor controller. Please try again."
else:
return "Error: Unexpected message format, cannot decode reply from motor controller. Data: " + line
return ""
conn = sqlite3.connect(db_path)
curs = conn.cursor()
#note time
p = subprocess.Popen("date +\"%Y-%m-%d %H:%M\"", stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
current_date = output
#Create needed folder structure
if not (os.path.exists(csv_path)):
os.makedirs(csv_path)
csv_path += "FaultLog.csv"
with open(csv_path, 'w+') as file:
file.write("Date:," + current_date[:10] + "\n")
file.write("Time:," + current_date[11:] + "\n\n")
#SEVCON Fault Retreival
file.write('Hours Ago [h], Minutes & Seconds Ago, Fault ID, Fault Name, Fault Cause, Fault Remedy\n')
#send password to gain access
p = subprocess.Popen("cansend can0 601#2B005002DF4BEFFA", cwd="/data/can-utils/", stdout=subprocess.PIPE, shell=True)
p = subprocess.Popen("candump -t A -n 1 -T 100 can0,581:7ff", cwd="/data/can-utils/", stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
for num in range(0,40):
pass
#select event through 4111
p = subprocess.Popen("cansend can0 601#2B114100" + hex(num)[2:].zfill(2) + "00EFFA", cwd="/data/can-utils/", stdout=subprocess.PIPE, shell=True)
p = subprocess.Popen("candump -t A -n 1 -T 100 can0,581:7ff", cwd="/data/can-utils/", stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
#send request for event ID through 4112
p = subprocess.Popen("(sleep 0.1; cansend can0 601#4012410100000000; cansend can0 601#4012410200000000; cansend can0 601#4012410300000000;) &", cwd="/data/can-utils/", stdout=subprocess.PIPE, shell=True)
p = subprocess.Popen("candump -t A -n 3 -T 500 can0,581:7ff", cwd="/data/can-utils/", stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
message = ""
if len(output) > 0: # got the response message
lines = output.strip().split("\n")
for line in lines:
message = parse_msg(line)
else:
message = "Error: Did not receive reply from motor controller."
if message == "":
#query database for fault description and remedy
curs.execute("SELECT * FROM FaultDictionary WHERE faultID = '" + str(faultID) + "'") #faultID, message, description, action
for row in curs: #only ever one, since unique
#record to csv
file.write(str(hours) + "," + str(minutes) + "," + str(row[0]) + "," + str(row[1]) + "," + str(row[2]) + "," + str(row[3]) + "\n")
#print str(hours) + "," + str(minutes) + "," + str(row[0]) + "," + str(row[1]) + "," + str(row[2]) + "," + str(row[3]) + "\n"
else:
print message
break
#BMS Fault Retrieval
#file.write('\n\nFault ID\n')
if not message == "":
os.remove(csv_path)
conn.close()
tldr; PHP exec() 函数调用 python 脚本。 Exec() 应该等待您调用的任何内容完成。对某些脚本这样做,但对其他脚本不这样做。
Exec 是一个同步阻塞调用,当没有 &
传递给参数时强制程序/执行在后台发生。
这让我相信处理请求的 Apache
实例的所有者没有执行 Python
脚本的权限。
您应该相应地调整脚本或 Apache 用户的权限。