Category Archives: Linux

PHP在Linux下运行Shell命令

原本在本机开发PHP的时候,Shell调用一切正常。上线的时候才反应到线上的服务器对权限做了严格的控制,一顿折腾之后梳理出在严格权限控制的Linux上如何通过Nginx/Apache 以Web的方式调用Shell命令,比如调用java编译或者执行java程序。

Web服务器使用www用户启动。分为两种情况:一种是命令是通过root安装的,并不能直接把权限直接赋给www用户,比如/usr/local/nginx/sbin/nginx;一种是www用户对要执行的命令有绝对的权限,但是由于缺少某些环境变量,执行的程序如果用到了这些变量就得提前再次设定环境变量。

先说第一种,其实php.ini里面已经定义了不可以调用的命令,默认情况下exec, system之类都不能执行。首先要去php.ini里面把

disable_functions=

这一项里面定义的那些调用Shell脚本的函数移出列表,然后重启Nginx的PHP-PFM或者Apache。可以测试一下

<?php echo exec(“pwd”); ?>

正常情况下应该就可以看到当前的路径信息了。但是要想执行一些root才能执行的命令,比如重新加载Nginx配置文件,还需要一些额外的操作,这里参考http://bbs.chinaunix.net/thread-3693263-1-1.html

1、设置 sudo 配置文件 可写权限
chmod u+w /etc/sudoers

2、增加 www 用户的 nginx 脚本管理权限
www     ALL=(root)      NOPASSWD: /etc/init.d/nginx

3、关闭 【强制控制台登录】执行
【非常重要】,注释该行 我的问题就出在这里,开启了这个选项之后。在PHP中怎么调用,都没有执行结果
#Defaults    requiretty

4、还原 sudo 配置权限  440
【非常重要】,如果不还原权限。在PHP中怎么调用,都没有执行结果。
chmod u-w /etc/sudoers

5、调用php
$result2 = exec(“/usr/bin/sudo /etc/init.d/nginx stop”,$result);
var_dump($result);
var_dump($result2);

再看看如果调用Java编译并执行。www用户拥有对/work/java目录的执行权限。直接上代码:

Java的,文件名”TestJava.java”

public class TestJava{
public static void main(String[] args) {
System.out.println(“Hello World!”);
}
}

PHP的,文件名”test.php”

<?php

function del_file($file){
if(file_exists($file) && unlink($file) ){
echo “del “.$file.”<br />\r\n”;
}
}

function execute($exe){
echo $exe.”<br />\r\n”;
$r=exec($exe, $res);
var_dump($res);
echo “<br />———————-<br />\r\n”;
var_dump($r);
echo “<br />———————-<br />\r\n”;
}

$target_file = “TestJava.class”;
$output_file = “output.txt”;
$src=”/work/web/services.adsage.com/deploy/monitor/test/TestJava.java”;
$bin=”TestJava”;
$jcommon = “export JAVA_HOME=/work/java\nexport JRE_HOME=$JAVA_HOME/jre\nexport PATH=$JAVA_HOME/bin:$PATH\n/work/java/bin/”;
$javac=$jcommon.”javac “.$src;
$javab=$jcommon.”java “.$bin.” >> “.$output_file;
del_file($target_file);
del_file($output_file);

execute($javac);
execute($javab);

echo “final:<br />\r\n”;
$output=file_get_contents($output_file);
echo $output;
?>

通过Web浏览结果:

del TestJava.class
del output.txt
export JAVA_HOME=/work/java export JRE_HOME=/jre export PATH=/bin: /work/java/bin/javac /work/web/services.adsage.com/deploy/monitor/test/TestJava.java
array(0) { }
———————-
string(0) “”
———————-
export JAVA_HOME=/work/java export JRE_HOME=/jre export PATH=/bin: /work/java/bin/java TestJava >> output.txt
array(0) { }
———————-
string(0) “”
———————-
final:
Hello World!

 

LuManager单独安装mysqli手记

在开始之前,首先试一下这个这个帖子里提到的方法

http://www.zijidelu.org/forum.php?mod=viewthread&tid=46214

如果不行,按照下面的方法进行(不仅仅适用于LuManager,如果是自己编译安装的php也可以这么做):

首先确定你正在使用的php版本以及php.ini的位置,LuManager自带了几个版本。如果是默认安装,应该是5.2.17。php.ini的位置应该是在

/usr/local/php_fcgi/lib/php.ini

要确定这些信息,可以自己编写一个 info.php

 <?php

phpinfo();

?>

把文件存放到网站根目录,然后浏览一下。

比如 http://yourdomain.com/info.php

到上述帖子里提到的LuManager的安装源码包里,我的解压到了/root/zijidelu_install路径下

进入LuNamp的soft路径

cd /root/zijidelu_install/LuNamp/soft

用ls查看一下,应该有这个文件

ls php-5.2.17.tar.gz

解压缩

tar -zxvf php-5.2.17.tar.gz

进入mysqli的安装路径

cd php-5.2.17/ext/mysqli

这里是mysqli的源码,编译之前我们还需要借助phpize这个工具(感谢@一只猪同学的帮助:-)),它存在于你的php安装路径,比如

/usr/local/php_fcgi/bin/phpize

在当前路径下运行一下,看到如下提示:

Configuring for:

PHP Api Version:         20041225

Zend Module Api No:      20060613

Zend Extension Api No:   220060519

configure.in:3: warning: prefer named diversions

configure.in:3: warning: prefer named diversions

继续运行下面这几个命令

 ./configure -with-php-config=/usr/local/php_fcgi/bin/php-config -with-mysqli=/usr/local/mysql/bin/mysql_config

make

make install

最后会看到这个提示:

Installing shared extensions:     /usr/local/php_fcgi/lib/php/extensions/no-debug-non-zts-20060613/

说明安装成功。

从LuManager后台重启一下ngix(如果你只用Apache那就重启一下Apache)

再刷新一下info.php,搜索mysqli,如果还搜不到就得自己编辑一下php.ini了

编辑之前double check一下mysqli.so是不是已经安装到上述路径了

cd  /usr/local/php_fcgi/lib/php/extensions/no-debug-non-zts-20060613/

ls

如果看到mysqli.so就继续

vim /usr/local/php_fcgi/lib/php.ini

输入

/mysqli

然后回车,定位到这一行

;extension=php_mysqli.dll

输入i,进入编辑模式,然后在这之前或者之后加入一行

extension=mysqli.so

按下ESC,然后输入

:wq

如果对vim编辑不熟悉可以从LuManager后台在线编辑php.ini

保存之后重启一下ngix

再次查看info.php

mysqli

 

MysqlI Support enabled
Client API library version 5.1.56
Client API header version 5.1.56
MYSQLI_SOCKET /tmp/mysql.sock

 

 

LuManager安装过程导入Mysql失败的解决办法

LuManager是一个优秀的国产Linux服务器管理软件,集成了Apache,Nigix,MySQL,FTP,Bind,Memcache,PHP5等软件包,可以实现Apache与Nigix的一键切换,多服务器负载均衡,域名智能解析,用户管理,流量监测功能等。可以通过Web界面来管理整个服务器,还能一键安装DedeCMS,Discuz!等Web应用程序。

LuManager在安装和使用过程中可能碰到导入Mysql失败的情况。

一般有2种情况:

情况1 安装MySQL时出错

Mysql 安装成功,继续安装LuNamp1.0

Mysql was successfully installed! Continue…

已耗时:30 分钟

Runtime: 30 分钟

ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock’ (2)

MySQL数据导入不成功,可能是数据库没启动,或者是MySQL没安装成功,请重装一次试试!

Mysql data was not imported!

LuNamp安装失败

LuNamp was install failed

分析:

原来系统安装了一个MySQL,在系统原有MySQL没有停止服务的时候开始安装了LuManager,有可能是原有MySQL服务产生了影响。

解决:

杀死系统中正在运行的MySQL

方法1

如果你知道原有的MySQL服务器root用户密码,那么通过这个命令就能停止(忘记密码的看方法2):

mysqladmin -uroot -p’password’ shutdown

注意:

1. /etc/init.d/mysql stop 并不是正确的停止mysql服务的方法!

2. 如果你试图通过 /usr/local/LuNamp/cmd 目录下的 mysql-stop 来停止服务,那么你可能会碰到如下提示:

protest1:/usr/local/LuNamp/cmd# ./mysql-stop

1

MySQL manager or server PID file could not be found! failed!

可以通过方法2来解决

方法2

首先确保当前是root用户,运行如下命令:

protest1:/usr/local/LuNamp/cmd# ps -Af | grep mysqld

返回结果如下(注意加粗的那一行,那个PID就是MySQL的进程ID):

root      6928     1  0 Jun21 ?        00:00:00 /bin/sh /usr/bin/mysqld_safe

mysql    17427  6928  0 14:56 ?        00:00:00 /usr/sbin/mysqld –basedir=/usr –datadir=/var/lib/mysql –user=mysql –pid-file=/var/run/mysqld/mysqld.pid –skip-external-locking –port=3306 –socket=/var/run/mysqld/mysqld.sock

root     17428  6928  0 14:56 ?        00:00:00 logger -p daemon.err -t mysqld_safe -i -t mysqld

root     17460 17340  0 14:58 pts/2    00:00:00 grep mysqld

接着运行

protest1:/usr/local/LuNamp/cmd#Kill 17427

杀死了MySQL进程后,重新运行./zijidelu_install.sh就可以了

情况2 进入系统时出错,提示:

Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock'(2)

截图:

解决方法:

首先参考情况1的方法1或者方法2来杀死当前正在运行的MySQL服务,然后以root用户身份进入

/usr/local/LuNamp/cmd

运行当前目录的mysql-start

protest1:/usr/local/LuNamp/cmd#./mysql-start

然后刷新LuManager的Web界面应该就能顺利进入了:-)

 

WinSCP跨Linux(多Linux台机器之间)拷贝传输文件

 

这纯属一个使用技巧,找了很多LinuxWindows客户端,貌似都不能在同一个用户界面上跨机器拷贝传输文件,用来用去还是WinSCP顺手,以前跨机器传输的时候都是开多个窗口,拖放。今天偶然发现WinSCP也可以在同一个用户界面上跨机器拷贝传输文件。

 

首先要确保WinSCP的工具栏“会话按钮”是显示状态,方便在多台Linux之间切换界面

WinSCP会话按钮

点击“会话按钮”工具栏的倒数第二个按钮,可以登录更多的Linux机器(注意:要拷贝的文件的目标机器必须先在这里登录)

WinSCP打开更多会话

在某一台需要拷贝的文件上单击鼠标右键,选择“远程复制”

WinSCP远程复制菜单

在新弹出的窗口中“目标会话”就可以选择其他的Linux机器以及对应的目录了。

WinSCP远程复制对话框

缺点就是不能同时拷贝到多台机器,以及文件拷贝实际上是先拷贝到本地,再拷贝到远程