PHP exec 没有按预期 运行 我的脚本
PHP exec doesn't run my script as intended
各位程序员,
我正在做我的学士项目,遇到了一些问题。
目标是创建一个网络应用程序,可以操作和修改 I/O WAGO PLC 750-8202(您可以将其想象成某种工业 Raspberry PI)运行使用 lighttpd 网络服务器安装嵌入式 linux。我制作了一些使用 PLC 提供的 DAL(HAL) 函数的 C 脚本。
现在我想 link 它与我的网站 application/site。我有一个简单的 PHP 页面(忽略按钮,它什么都不做):
<html>
<head>
<title>PHP Test</title>
</head>
<body>
<button value="CLICK ME">CLICK ME</button>
<?php
echo system("kbusdemo1");
?>
</body>
</html>
如您所见,我正在调用 kbusdemo1 脚本。它应该打印数字输入的值。如果我以 root 身份从连接到我的 PLC 的 SSH 终端调用它,它工作得很好。但是,如果我从 PHP 站点调用它(如上所示),它会执行但不显示数字输入值,而是显示错误 "No device found on KBUS"。您可以在下面的代码中看到确切的行。
KBUS是连接PLC所有input/output模块的总线。基本上看起来它没有正确执行PLC开发人员提供的功能。
这里是用C写的代码(kbusdemo1.c)
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <sched.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <dal/adi_application_interface.h>
#define KBUS_MAINPRIO 40
int
main(void)
{
// vars for ADI-interface
tDeviceInfo deviceList[10]; // the list of devices given by the ADI
size_t nrDevicesFound; // number of devices found
size_t nrKbusFound; // position of the kbus in the list
tDeviceId kbusDeviceId; // device ID from the ADI
tApplicationDeviceInterface * adi; // pointer to the application interface
uint32_t taskId = 0; // task Id
tApplicationStateChangedEvent event; // var for the event interface of the ADI
int AnWriteSelect, AnReadSelect, i, j, k, DigWriteOffset = 32, DigReadOffset = 32, vyber;
int DigWrite[8] = {0}, DigRead[8] = {0};
char DigWriteBuff[8];
int16_t AnRead, AnWrite;
bool loop = false;
struct sched_param s_param;
// program start
//printf("**************************************************\n");
//printf("*** KBUS test app ***\n");
//printf("**************************************************\n");
// clear process memory
memset(DigWrite, 0, sizeof(DigWrite));
memset(DigWriteBuff, 0, sizeof(DigWriteBuff));
memset(DigRead, 0, sizeof(DigRead));
// connect to ADI-interface
adi = adi_GetApplicationInterface();
// init interface
adi->Init();
// scan devices
adi->ScanDevices();
adi->GetDeviceList(sizeof(deviceList), deviceList, &nrDevicesFound);
// find kbus device
nrKbusFound = -1;
for (i = 0; i < nrDevicesFound; ++i)
{
if (strcmp(deviceList[i].DeviceName, "libpackbus") == 0)
{
nrKbusFound = i;
printf("KBUS device found as %i\n", i);
}
}
// kbus not found > exit
if (nrKbusFound == -1)
{
printf("No device found on KBUS\n");
adi->Exit(); // disconnect ADI-Interface
return -1; // exit program
}
// switch to RT Priority
s_param.sched_priority = KBUS_MAINPRIO;
sched_setscheduler(0, SCHED_FIFO, &s_param);
printf("Switch to RT priority 'KBUS_MAINPRIO'\n");
// open kbus device
kbusDeviceId = deviceList[nrKbusFound].DeviceId;
if (adi->OpenDevice(kbusDeviceId) != DAL_SUCCESS)
{
printf("Opening KBUS device failed\n");
adi->Exit(); // disconnect ADI-Interface
return -2; // exit program
}
//printf("Otevření KBUS zařízení OK\n");
// set application state to "Unconfigured" to let library drive kbus by them selve.
// In this mode library set up a thread who drive the kbus cyclic.
event.State = ApplicationState_Unconfigured;
if (adi->ApplicationStateChanged(event) != DAL_SUCCESS)
{
// Set application state to "Unconfigured" failed
printf("Setting Unconfigured application state failed\n");
adi->CloseDevice(kbusDeviceId); // close kbus device
adi->Exit(); // disconnect ADI-Interface
return -3; // exit programm
}
printf("Unconfigured application state OK\n");
adi->WatchdogTrigger();
adi->ReadStart(kbusDeviceId, taskId);
for (k = 0; k < 8; k++)
{
adi->ReadBool(kbusDeviceId,taskId,DigReadOffset,(int*) &DigRead[k]);
DigReadOffset++;
}
adi->ReadEnd(kbusDeviceId, taskId);
for(k = 0; k < 8; k++)
printf("%d ",DigRead[k]);
printf("\n \n");
DigReadOffset = 32;
adi->CloseDevice(kbusDeviceId);
adi->Exit();
return 0;
}
所以,问题是,我使用的方法是否正确? PHP exec适合这种应用吗?如果是这样,知道我哪里做错了吗?
我知道这是一个特定于设备的问题。我目前没有想法,任何能给我指明正确方向的提示都是无价的。
感谢您的宝贵时间。
编辑
好的,我尝试使用
编辑 sudoers
sudo nano /etc/sudoers
Visudo 未在 PLC linux 系统中实现。我将其更改为下面发布的代码,但是如果我按照您的建议(使用 su www)尝试 运行,它仍然不起作用。我做错了什么?
感谢您的建议。
# sudoers file.
#
# This file MUST be edited with the 'visudo' command as root.
#
# See the sudoers man page for the details on how to write a sudoers file.
#
# Host alias specification
# User alias specification
# Cmnd alias specification
# Defaults specification
# Runas alias specification
# User privilege specification
root ALL=(ALL) SETENV: ALL
admin ALL=NOPASSWD: /etc/config-tools/get_user_info
user ALL=NOPASSWD: /etc/config-tools/get_user_info
www ALL=(ALL) NOPASSWD:ALL
# Uncomment to allow people in group wheel to run all commands
# and set environment variables.
# %wheel ALL=(ALL) SETENV: ALL
# Same thing without a password
# %wheel ALL=(ALL) NOPASSWD: SETENV: ALL
# Samples
# %users ALL=/sbin/mount /cdrom,/sbin/umount /cdrom
# %users localhost=/sbin/shutdown -h now
如果你 运行 脚本作为 root,它比 lighthttpd 是 运行ning 的用户有另一个权限。
- 为用户或组设置适当的权限(www 或 www-data,参见 lighthttpd 配置)
检查此用户下的 运行ning,在控制台中从 root 使用
切换
# su - www
各位程序员,
我正在做我的学士项目,遇到了一些问题。
目标是创建一个网络应用程序,可以操作和修改 I/O WAGO PLC 750-8202(您可以将其想象成某种工业 Raspberry PI)运行使用 lighttpd 网络服务器安装嵌入式 linux。我制作了一些使用 PLC 提供的 DAL(HAL) 函数的 C 脚本。
现在我想 link 它与我的网站 application/site。我有一个简单的 PHP 页面(忽略按钮,它什么都不做):
<html>
<head>
<title>PHP Test</title>
</head>
<body>
<button value="CLICK ME">CLICK ME</button>
<?php
echo system("kbusdemo1");
?>
</body>
</html>
如您所见,我正在调用 kbusdemo1 脚本。它应该打印数字输入的值。如果我以 root 身份从连接到我的 PLC 的 SSH 终端调用它,它工作得很好。但是,如果我从 PHP 站点调用它(如上所示),它会执行但不显示数字输入值,而是显示错误 "No device found on KBUS"。您可以在下面的代码中看到确切的行。
KBUS是连接PLC所有input/output模块的总线。基本上看起来它没有正确执行PLC开发人员提供的功能。
这里是用C写的代码(kbusdemo1.c)
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <sched.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <dal/adi_application_interface.h>
#define KBUS_MAINPRIO 40
int
main(void)
{
// vars for ADI-interface
tDeviceInfo deviceList[10]; // the list of devices given by the ADI
size_t nrDevicesFound; // number of devices found
size_t nrKbusFound; // position of the kbus in the list
tDeviceId kbusDeviceId; // device ID from the ADI
tApplicationDeviceInterface * adi; // pointer to the application interface
uint32_t taskId = 0; // task Id
tApplicationStateChangedEvent event; // var for the event interface of the ADI
int AnWriteSelect, AnReadSelect, i, j, k, DigWriteOffset = 32, DigReadOffset = 32, vyber;
int DigWrite[8] = {0}, DigRead[8] = {0};
char DigWriteBuff[8];
int16_t AnRead, AnWrite;
bool loop = false;
struct sched_param s_param;
// program start
//printf("**************************************************\n");
//printf("*** KBUS test app ***\n");
//printf("**************************************************\n");
// clear process memory
memset(DigWrite, 0, sizeof(DigWrite));
memset(DigWriteBuff, 0, sizeof(DigWriteBuff));
memset(DigRead, 0, sizeof(DigRead));
// connect to ADI-interface
adi = adi_GetApplicationInterface();
// init interface
adi->Init();
// scan devices
adi->ScanDevices();
adi->GetDeviceList(sizeof(deviceList), deviceList, &nrDevicesFound);
// find kbus device
nrKbusFound = -1;
for (i = 0; i < nrDevicesFound; ++i)
{
if (strcmp(deviceList[i].DeviceName, "libpackbus") == 0)
{
nrKbusFound = i;
printf("KBUS device found as %i\n", i);
}
}
// kbus not found > exit
if (nrKbusFound == -1)
{
printf("No device found on KBUS\n");
adi->Exit(); // disconnect ADI-Interface
return -1; // exit program
}
// switch to RT Priority
s_param.sched_priority = KBUS_MAINPRIO;
sched_setscheduler(0, SCHED_FIFO, &s_param);
printf("Switch to RT priority 'KBUS_MAINPRIO'\n");
// open kbus device
kbusDeviceId = deviceList[nrKbusFound].DeviceId;
if (adi->OpenDevice(kbusDeviceId) != DAL_SUCCESS)
{
printf("Opening KBUS device failed\n");
adi->Exit(); // disconnect ADI-Interface
return -2; // exit program
}
//printf("Otevření KBUS zařízení OK\n");
// set application state to "Unconfigured" to let library drive kbus by them selve.
// In this mode library set up a thread who drive the kbus cyclic.
event.State = ApplicationState_Unconfigured;
if (adi->ApplicationStateChanged(event) != DAL_SUCCESS)
{
// Set application state to "Unconfigured" failed
printf("Setting Unconfigured application state failed\n");
adi->CloseDevice(kbusDeviceId); // close kbus device
adi->Exit(); // disconnect ADI-Interface
return -3; // exit programm
}
printf("Unconfigured application state OK\n");
adi->WatchdogTrigger();
adi->ReadStart(kbusDeviceId, taskId);
for (k = 0; k < 8; k++)
{
adi->ReadBool(kbusDeviceId,taskId,DigReadOffset,(int*) &DigRead[k]);
DigReadOffset++;
}
adi->ReadEnd(kbusDeviceId, taskId);
for(k = 0; k < 8; k++)
printf("%d ",DigRead[k]);
printf("\n \n");
DigReadOffset = 32;
adi->CloseDevice(kbusDeviceId);
adi->Exit();
return 0;
}
所以,问题是,我使用的方法是否正确? PHP exec适合这种应用吗?如果是这样,知道我哪里做错了吗?
我知道这是一个特定于设备的问题。我目前没有想法,任何能给我指明正确方向的提示都是无价的。
感谢您的宝贵时间。
编辑
好的,我尝试使用
编辑 sudoerssudo nano /etc/sudoers
Visudo 未在 PLC linux 系统中实现。我将其更改为下面发布的代码,但是如果我按照您的建议(使用 su www)尝试 运行,它仍然不起作用。我做错了什么?
感谢您的建议。
# sudoers file.
#
# This file MUST be edited with the 'visudo' command as root.
#
# See the sudoers man page for the details on how to write a sudoers file.
#
# Host alias specification
# User alias specification
# Cmnd alias specification
# Defaults specification
# Runas alias specification
# User privilege specification
root ALL=(ALL) SETENV: ALL
admin ALL=NOPASSWD: /etc/config-tools/get_user_info
user ALL=NOPASSWD: /etc/config-tools/get_user_info
www ALL=(ALL) NOPASSWD:ALL
# Uncomment to allow people in group wheel to run all commands
# and set environment variables.
# %wheel ALL=(ALL) SETENV: ALL
# Same thing without a password
# %wheel ALL=(ALL) NOPASSWD: SETENV: ALL
# Samples
# %users ALL=/sbin/mount /cdrom,/sbin/umount /cdrom
# %users localhost=/sbin/shutdown -h now
如果你 运行 脚本作为 root,它比 lighthttpd 是 运行ning 的用户有另一个权限。
- 为用户或组设置适当的权限(www 或 www-data,参见 lighthttpd 配置)
检查此用户下的 运行ning,在控制台中从 root 使用
切换# su - www