如何使用php网页上的expect脚本?

时间:2022-10-28 14:33:12

When i try to execute a program from php5 on my debian, the webpage freeze and the program do nothing. This script works when i call it from the command line. Safe mode is disabled. Echo stdout doesnt work (because of the freeze). I read some answers in google which tells of www permissions but if someone here have a quick and simple response...

当我尝试从我的debian上的php5执行程序时,网页冻结并且程序什么都不做。当我从命令行调用它时,此脚本有效。安全模式已禁用。 Echo stdout不起作用(因为冻结)。我在google中读到了一些有关www权限的答案,但是如果有人在这里有一个快速简单的回复...

How to debug this ?

如何调试?

The php call

exec("expect scripts/sshtest.exp $module");

The script code (which i found here http://bash.cyberciti.biz/security/expect-ssh-login-script/)

#!/usr/bin/expect -f
# set Variables
set module [lrange $argv 0 0]
set timeout -1
# rsync 
spawn rsync -aCb --progress --delete --backup-dir=/var/www/blabla.com/rsyncBackups/BackupedFilesFromServer23_on_  /var/www/blabla/$module  -e ssh root@10.10.10.10:/root/$module
match_max 1000000
# Look for passwod prompt
expect "*?assword:*"
# Send password 
send -- "THEPASSWORD\r"
# send blank line (\r) to make sure we get back to gui
send -- "\r"
expect eof

8 个解决方案

#1


Try

passthru("expect scripts/sshtest.exp $module 2>&1");

The 2>&1 redirects stderr to stdout and using passthru instead of exec will give you all the output.

2>&1将stderr重定向到stdout并使用passthru而不是exec将为您提供所有输出。

#2


Why use expect at all? Set up rsync to use public/private keys (see http://troy.jdmz.net/rsync/index.html) and you will not have to use expect to enter passwords.

为什么要使用期望?设置rsync以使用公钥/私钥(请参阅http://troy.jdmz.net/rsync/index.html),您不必使用expect来输入密码。

#3


I had this exact same problem and it was making me nuts. I'm a little late to the party, but I figured I'd post the solution that solved my issue in case someone else comes across this thread and has the same problem.

我有这个完全相同的问题,它让我疯了。我参加派对有点晚了,但我想我会发布一个解决了我的问题的解决方案,万一其他人遇到这个帖子并遇到同样的问题。

My symptoms were the same as the OP. I would run the PHP script, it would kick off the Expect script via shell_execute, and then it would just hang forever. The problem turned out to be due to the following question that was being asked to the apache user when the Expect script ran:

我的症状与OP相同。我会运行PHP脚本,它将通过shell_execute启动Expect脚本,然后它将永远挂起。问题原来是由于在Expect脚本运行时向apache用户询问的以下问题:

The authenticity of host 'xx.xx.xx.xx (xx.xx.xx.xx)' can't be established. RSA key fingerprint is xxxxx. Are you sure you want to continue connecting (yes/no)?

无法建立主机'xx.xx.xx.xx(xx.xx.xx.xx)'的真实性。 RSA密钥指纹是xxxxx。您确定要继续连接(是/否)吗?

This question wouldn't come up for me when I ran the script from the command line since I believe the question is only asked once if the host added to the host list.

当我从命令行运行脚本时,这个问题不会出现,因为我认为只有主机添加到主机列表时才会询问一次该问题。

To fix the problem, I added this code in before the spot where I entered in the password:

为了解决这个问题,我在输入密码的地方之前添加了这段代码:

expect "*you sure you want to continue*"
send -- "yes\r"

That resulted in this (I had my PHP script return all of the output from the Expect script):

这导致了这个(我的PHP脚本返回了Expect脚本的所有输出):

The authenticity of host 'xx.xx.xx.xx (xx.xx.xx.xx)' can't be established. RSA key fingerprint is xxxxx. Are you sure you want to continue connecting (yes/no)? yes Failed to add the host to the list of known hosts (/var/www/.ssh/known_hosts).

无法建立主机'xx.xx.xx.xx(xx.xx.xx.xx)'的真实性。 RSA密钥指纹是xxxxx。您确定要继续连接(是/否)吗?是无法将主机添加到已知主机列表(/var/www/.ssh/known_hosts)。

However, directly after that the password prompt came up and the password was entered in correctly. From that point forward the Expect script ran fine.

但是,在此之后,密码提示出现并正确输入密码。从那时起,Expect脚本运行良好。

#4


Another common catch is that when you run the command you are a different user from when apache runs the command. And often, the user apache runs as has very limited set up for security reasons.

另一个常见的问题是,当您运行该命令时,您与apache运行命令时的用户不同。通常,出于安全原因,用户apache运行的设置非常有限。

eg. The apache user might not have the right paths installed. Use the absolute path to expect, not the relative. You can find this by running 'which expect'.

例如。 apache用户可能没有安装正确的路径。使用绝对路径期望,而不是相对。你可以通过运行'which expect'来找到它。

Try to 'su' to the same user apache runs as (look for 'User' command in apache conf file or simply browse 'ps aux') and run the command and see what errors you get.

尝试'su'到同一个用户apache运行(在apache conf文件中查找'User'命令或只是浏览'ps aux')并运行命令,看看你得到了什么错误。

#5


The "user" or the "group" PHP is using to exec commands may have insufficient rights to execute one cmd in the script (or even expect itself). Have you tried using sudo to run the script as the same user you have been testing with?

PHP用于执行命令的“用户”或“组”可能没有足够的权限在脚本中执行一个cmd(甚至可能期望自己)。您是否尝试使用sudo以与您一直在测试的用户身份运行脚本?

#6


Are you running mod___php or suPHP?
mod_php runs scripts as the Apache user so try to su to the apache user and then run the php script from shell "php scriptname.php" and see if it's working.
If you use suPHP then su to the user under which you've setup apache to tun those scripts and the so the same "php scriptname.php" and check for the output.

你在运行mod___php还是suPHP? mod_php作为Apache用户运行脚本,所以尝试su到apache用户,然后从shell“php scriptname.php”运行php脚本,看看它是否正常工作。如果你使用suPHP然后su给你设置apache的用户来修改这些脚本,那么相同的“php scriptname.php”并检查输出。

#7


Be careful with expect over php that you wait long enough before putting in your next command, and also that all your variables are correct. Greg's pointer on using 2>&1 saved me a lot of hassle.

小心期望在你输入你的下一个命令之前等待足够长的php,并且你所有的变量都是正确的。格雷格使用2>&1的指针为我省去了很多麻烦。

try running

passthru("expect -d scripts/sshtest.exp $module");

-d will save your life in expect.

-d将拯救你的生命。

#8


  1. If you're using exec instead of passthru, do it in this way: exec("/bin/bash -c 'command' > logfile_to_read_or_include_next");

    如果您使用的是exec而不是passthru,请以这种方式执行:exec(“/ bin / bash -c'command'> logfile_to_read_or_include_next”);

  2. If you want to mess your system with spawned processes:

    如果你想用生成的进程搞乱你的系统:

write a perl/c script, that would process your requests.

编写一个perl / c脚本,用于处理您的请求。

#!/usr/bin/perl -w
use HTTP::Daemon;
use HTTP::Status;
use strict;
  my $d = HTTP::Daemon->new(LocalPort => 10050) || die;
  print "Please contact me at: <URL:", $d->url, ">\n";
  while (my $c = $d->accept) {
      while (my $r = $c->get_request) {
          if ($r->method eq 'GET' and $r->uri->path =~/addRequest-(.*)$/) {
                # variable $1 now has your request.
                 my $rq = $1; # wash me!
                # assign it a #ID, 
                 my $id = "id".time().rand(100);
                 &run_in_another_thread($rq,$id);
              $c->send_responce($id);
          } elsif ($r->method eq 'GET' and $r->uri->path =~/seeRequest-(.*)$/) {
             $c->send_responce( &get_result_for_id($1) );
          }
          else {
              $c->send_error(RC_FORBIDDEN)
          }
      }
      $c->close;
      undef($c);
  }
}

sub run_in_another_thread {
 my ($rq,$id) = @_;
 my $evil = threads->create( sub { qx"/bin/bash -c '$rq' > logfile_$id.log" # start process
  }->detach();
}

sub get_result_for_id {
 my ($id) = @_;
 return qx"cat logfile_$id.log";
}

Next, get 127.0.0.1/addRequest-expect from your code, and voila..

接下来,从您的代码中获取127.0.0.1/addRequest-expect,并且瞧..

#1


Try

passthru("expect scripts/sshtest.exp $module 2>&1");

The 2>&1 redirects stderr to stdout and using passthru instead of exec will give you all the output.

2>&1将stderr重定向到stdout并使用passthru而不是exec将为您提供所有输出。

#2


Why use expect at all? Set up rsync to use public/private keys (see http://troy.jdmz.net/rsync/index.html) and you will not have to use expect to enter passwords.

为什么要使用期望?设置rsync以使用公钥/私钥(请参阅http://troy.jdmz.net/rsync/index.html),您不必使用expect来输入密码。

#3


I had this exact same problem and it was making me nuts. I'm a little late to the party, but I figured I'd post the solution that solved my issue in case someone else comes across this thread and has the same problem.

我有这个完全相同的问题,它让我疯了。我参加派对有点晚了,但我想我会发布一个解决了我的问题的解决方案,万一其他人遇到这个帖子并遇到同样的问题。

My symptoms were the same as the OP. I would run the PHP script, it would kick off the Expect script via shell_execute, and then it would just hang forever. The problem turned out to be due to the following question that was being asked to the apache user when the Expect script ran:

我的症状与OP相同。我会运行PHP脚本,它将通过shell_execute启动Expect脚本,然后它将永远挂起。问题原来是由于在Expect脚本运行时向apache用户询问的以下问题:

The authenticity of host 'xx.xx.xx.xx (xx.xx.xx.xx)' can't be established. RSA key fingerprint is xxxxx. Are you sure you want to continue connecting (yes/no)?

无法建立主机'xx.xx.xx.xx(xx.xx.xx.xx)'的真实性。 RSA密钥指纹是xxxxx。您确定要继续连接(是/否)吗?

This question wouldn't come up for me when I ran the script from the command line since I believe the question is only asked once if the host added to the host list.

当我从命令行运行脚本时,这个问题不会出现,因为我认为只有主机添加到主机列表时才会询问一次该问题。

To fix the problem, I added this code in before the spot where I entered in the password:

为了解决这个问题,我在输入密码的地方之前添加了这段代码:

expect "*you sure you want to continue*"
send -- "yes\r"

That resulted in this (I had my PHP script return all of the output from the Expect script):

这导致了这个(我的PHP脚本返回了Expect脚本的所有输出):

The authenticity of host 'xx.xx.xx.xx (xx.xx.xx.xx)' can't be established. RSA key fingerprint is xxxxx. Are you sure you want to continue connecting (yes/no)? yes Failed to add the host to the list of known hosts (/var/www/.ssh/known_hosts).

无法建立主机'xx.xx.xx.xx(xx.xx.xx.xx)'的真实性。 RSA密钥指纹是xxxxx。您确定要继续连接(是/否)吗?是无法将主机添加到已知主机列表(/var/www/.ssh/known_hosts)。

However, directly after that the password prompt came up and the password was entered in correctly. From that point forward the Expect script ran fine.

但是,在此之后,密码提示出现并正确输入密码。从那时起,Expect脚本运行良好。

#4


Another common catch is that when you run the command you are a different user from when apache runs the command. And often, the user apache runs as has very limited set up for security reasons.

另一个常见的问题是,当您运行该命令时,您与apache运行命令时的用户不同。通常,出于安全原因,用户apache运行的设置非常有限。

eg. The apache user might not have the right paths installed. Use the absolute path to expect, not the relative. You can find this by running 'which expect'.

例如。 apache用户可能没有安装正确的路径。使用绝对路径期望,而不是相对。你可以通过运行'which expect'来找到它。

Try to 'su' to the same user apache runs as (look for 'User' command in apache conf file or simply browse 'ps aux') and run the command and see what errors you get.

尝试'su'到同一个用户apache运行(在apache conf文件中查找'User'命令或只是浏览'ps aux')并运行命令,看看你得到了什么错误。

#5


The "user" or the "group" PHP is using to exec commands may have insufficient rights to execute one cmd in the script (or even expect itself). Have you tried using sudo to run the script as the same user you have been testing with?

PHP用于执行命令的“用户”或“组”可能没有足够的权限在脚本中执行一个cmd(甚至可能期望自己)。您是否尝试使用sudo以与您一直在测试的用户身份运行脚本?

#6


Are you running mod___php or suPHP?
mod_php runs scripts as the Apache user so try to su to the apache user and then run the php script from shell "php scriptname.php" and see if it's working.
If you use suPHP then su to the user under which you've setup apache to tun those scripts and the so the same "php scriptname.php" and check for the output.

你在运行mod___php还是suPHP? mod_php作为Apache用户运行脚本,所以尝试su到apache用户,然后从shell“php scriptname.php”运行php脚本,看看它是否正常工作。如果你使用suPHP然后su给你设置apache的用户来修改这些脚本,那么相同的“php scriptname.php”并检查输出。

#7


Be careful with expect over php that you wait long enough before putting in your next command, and also that all your variables are correct. Greg's pointer on using 2>&1 saved me a lot of hassle.

小心期望在你输入你的下一个命令之前等待足够长的php,并且你所有的变量都是正确的。格雷格使用2>&1的指针为我省去了很多麻烦。

try running

passthru("expect -d scripts/sshtest.exp $module");

-d will save your life in expect.

-d将拯救你的生命。

#8


  1. If you're using exec instead of passthru, do it in this way: exec("/bin/bash -c 'command' > logfile_to_read_or_include_next");

    如果您使用的是exec而不是passthru,请以这种方式执行:exec(“/ bin / bash -c'command'> logfile_to_read_or_include_next”);

  2. If you want to mess your system with spawned processes:

    如果你想用生成的进程搞乱你的系统:

write a perl/c script, that would process your requests.

编写一个perl / c脚本,用于处理您的请求。

#!/usr/bin/perl -w
use HTTP::Daemon;
use HTTP::Status;
use strict;
  my $d = HTTP::Daemon->new(LocalPort => 10050) || die;
  print "Please contact me at: <URL:", $d->url, ">\n";
  while (my $c = $d->accept) {
      while (my $r = $c->get_request) {
          if ($r->method eq 'GET' and $r->uri->path =~/addRequest-(.*)$/) {
                # variable $1 now has your request.
                 my $rq = $1; # wash me!
                # assign it a #ID, 
                 my $id = "id".time().rand(100);
                 &run_in_another_thread($rq,$id);
              $c->send_responce($id);
          } elsif ($r->method eq 'GET' and $r->uri->path =~/seeRequest-(.*)$/) {
             $c->send_responce( &get_result_for_id($1) );
          }
          else {
              $c->send_error(RC_FORBIDDEN)
          }
      }
      $c->close;
      undef($c);
  }
}

sub run_in_another_thread {
 my ($rq,$id) = @_;
 my $evil = threads->create( sub { qx"/bin/bash -c '$rq' > logfile_$id.log" # start process
  }->detach();
}

sub get_result_for_id {
 my ($id) = @_;
 return qx"cat logfile_$id.log";
}

Next, get 127.0.0.1/addRequest-expect from your code, and voila..

接下来,从您的代码中获取127.0.0.1/addRequest-expect,并且瞧..