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