php的exec给出的结果与在shell中运行脚本不同

时间:2016-06-01 04:47:44

标签: php linux shell exec expect

我制作了一个expect脚本来控制我的Mikrotik路由器(下面的代码)。

从shell运行脚本:

sudo -u www-data sh -c '/usr/bin/expect /full/path/to/Mikrotik_wifi.sh 192.168.0.1 username TopSecretPassword wlan1 status > /tmp/expect.log 2>&1'

产生预期结果('Wifi Status:'后的wifi信息):

$ cat /tmp/expect.log
Starting SSH Connection to 192.168.0.1
Sending credentials
Logged in
Wifi Status:
 /interface wireless print where name=wlan1
Flags: X - disabled, R - running
 0  R name="wlan1" mtu=1500 mac-address=AA:BB:CC:DD:EE:FF arp=enabled interface-type=Atheros AR9300 mode=ap-bridge ssid="SOMENAME" frequency=2412 band=2ghz-b/g
      channel-width=20mhz scan-list=default wireless-protocol=802.11 vlan-mode=no-tag vlan-id=1 wds-mode=disabled wds-default-bridge=none wds-ignore-ssid=no
      bridge-mode=disabled default-authentication=yes default-forwarding=yes default-ap-tx-limit=0 default-client-tx-limit=0 hide-ssid=no
      security-profile=WiFi-Sec compression=no
[username@APNAME] >

Logged out

尝试从php的exec()

运行它
exec("sh -c '/usr/bin/expect /full/path/to/Mikrotik_wifi.sh 192.168.0.1 username TopSecretPassword wlan1 status > /tmp/expect.log 2>&1'");
echo readfile("/tmp/expect.log");

在浏览器中显示意外结果(缺少wifi信息):

Starting SSH Connection to 192.168.0.1
Sending credentials
Logged in
Wifi Status:

[username@APNAME] >

Logged out

我期待的剧本

$ cat /full/path/to/Mikrotik_wifi.sh
#!/usr/bin/expect
set timeout 10
set host [lindex $argv 0]
set username [lindex $argv 1]
set username "$username+tc80w"
set password [lindex $argv 2]
set interface [lindex $argv 3]
set command [lindex $argv 4]
set pass "password:"
set prompt "] >"

# display on screen
log_user 0

# Connect
send_user "Starting SSH Connection to $host\n"
spawn /usr/bin/ssh -o StrictHostKeyChecking=no $username@$host

expect "$pass";
sleep .1;
send_user "Sending credentials\n"
send "$password";
sleep .1;
send "\n";
sleep .1;

expect "$prompt";
send_user "Logged in\n"

# Perform command
switch -regexp -- $command {
    {on} {
        send "/interface wireless enable numbers=$interface"
        sleep .1
        send "\r"
      send_user "Wifi ON\n"
    }
    {off} {
        send "/interface wireless disable numbers=$interface"
        sleep .1
        send "\r"
        send_user "Wifi OFF\n"
    }
    {status} {
      send_user "Wifi Status:\n"
        send "/interface wireless print where name=$interface"
        sleep .1
        send "\r"
        expect "$prompt";
        puts $expect_out(buffer)
    }
    default {
        send_user "Please select command: on, off, status\n"
    }
}

# Logout
sleep .1;
send "/quit";
sleep .1;
send "\n";
send_user "Logged out\n"
exit

我试过了

  • 禁用mikrotik的外壳颜色和大小:用户名+ tc80w(http://wiki.mikrotik.com/wiki/Manual%3aConsole_login_process#FAQ
  • 包括stderr:2>& 1
  • 写入文件而不是直接输出到浏览器:> /tmp/expect.log
  • 在exec调用中包含shell(sh -c)
  • 尝试了不同风格的exec:exec,shell_exec,system,passthru
  • 增加exec缓冲区大小:buffer 2000
  • 从exec的$ expect_out(缓冲区)中删除隐藏的字符:set clean [regsub -all {[^。,= [:alnum:]]} $ lineOfBuffer“”]
  • send_user vs puts没什么区别

系统信息

Debian GNU/Linux 8.2 (jessie)
expect version 5.45
PHP Version 5.6.14-0+deb8u1

有关如何修复/调试此问题的任何建议吗?

更新(1):

我已尝试使用

的expect脚本
log_user 1

虽然这不会改变结果,但它在浏览器中给出了这些符号:

  • [9999B
  • [K

更新(2):

我已尝试使用

的expect脚本
exp_internal 1

这给了我以下相关输出:

Wifi Status:
send: sending "/interface wireless print where name=wlan1" to { exp5 }
send: sending "\r" to { exp5 }

expect: does " " (spawn_id exp5) match glob pattern "] >"? no

expect: does " \r[username@APNAME] > \u001b[K/interface wireless print where name=wlan1" (spawn_id exp5) match glob pattern "] >"? yes
expect: set expect_out(0,string) "] >"

可能是命令没有被执行 - 我怎么能检查(mikrotik日志不会显示它...) - 然而,wifi开/关命令工作正常......

0 个答案:

没有答案