0基础自学linux运维-5.9-如何在php中执行linux命令或脚本

前言

一般运维web化会通过web调用脚本(python或shell脚本为主)或者直接执行linux命令,在这里我使用php执行linux命令讲起。

环境安装

安装环境是根据 

0基础自学linux运维-2.3-centos7.6安装LNMP(nginx1.16+mysql5.7+PHP7.3)

这篇文章安装的LNMP,其实只要安装nignx和php就行了,mysql没有用到可以不安装

如果是其它版本的PHP请看一下php.ini中的“disable_functions”,是否把exec、shell_exec去掉了

PHP程序执行函数

根据PHP官网知道 php程度执行函数有如下

escapeshellarg — 把字符串转码为可以在 shell 命令里使用的参数

escapeshellcmd — shell 元字符转义

exec — 执行一个外部程序

passthru — 执行外部程序并且显示原始输出

proc_close — 关闭由 proc_open 打开的进程并且返回进程退出码

proc_get_status — 获取由 proc_open 函数打开的进程的信息

proc_nice — 修改当前进程的优先级

proc_open — 执行一个命令,并且打开用来输入/输出的文件指针。

proc_terminate — 杀除由 proc_open 打开的进程

shell_exec — 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。

system — 执行外部程序,并且显示输出

其中exec、passthru 、shell_exec、 system 比较多具体使用方法请点击直关链接,这里就不再说了

例子

例1 使用exec命令

ecec官方介绍如下:

0基础自学linux运维-5.9-如何在php中执行linux命令或脚本_第1张图片

建立一个数据

mkdir -pv /disk1/t1

echo 'this is a.txt'>/disk1/t1/a.txt

echo 'this is b.txt'>/disk1/t1/b.txt

echo 'this is c1.txt 1'>/disk1/t1/c.txt

echo 'this is c1.txt 2'>>/disk1/t1/c.txt

echo 'this is c1.txt 3'>>/disk1/t1/c.txt

现在要执行ls -l /disk1/t1命令,用php操作为:

mkdir -pv /disk1/www

cd /disk1/www/

cat>ls.php<

exec("ls -l /disk1/t1/a.txt",\$output);

print_r(\$output);

?>

EOF

cat ls.php

使用php内置Web Server

为了能更直观地看到结果,我使用了php内置的web Server来启动,端口为8000,格式为:       php -S IP:port,我这里IP是192.168.3.76,端口想设置为8000,故命令为:

#进入要运行的php目录               

cd /disk1/www/ 

#执行php内置web Server

php -S 192.168.3.76:8000

执行php

打开浏览器输入:http://192.168.3.76:8000/ls.php,执行结果如下:


例2 使用 shell_exec 命令

如果上面例子可是返回多行结果会怎样,把ls.php代码中

exec("ls -l /disk1/t1/a.txt",\$output); 

改为 

exec("ls -l /disk1/t1",\$output);

显示所有目录,再执行试下

再换成用shell_exec试下,语法如下:

0基础自学linux运维-5.9-如何在php中执行linux命令或脚本_第2张图片

把ls代码改为

$output = shell_exec("ls -l /disk1/t1");

echo "

$output
";

在浏览器运行一下:

0基础自学linux运维-5.9-如何在php中执行linux命令或脚本_第3张图片
是不是比上面的友好很多啦^_^

再把 ls -l /disk1/t1 改为查看 c.txt内容

$output = shell_exec("cat /disk1/t1/c.txt");

再按F5刷新一下浏览器查看结果

0基础自学linux运维-5.9-如何在php中执行linux命令或脚本_第4张图片
没问题



php权限问题

改为查看/var/log/messages前3行

$output = shell_exec("head -3 /var/log/messages");

为了能在页面显示错误,我在

ini_set('display_errors',1); //错误信息

ini_set('display_startup_errors',1);    //php启动错误信息 

error_reporting(-1);                    //打印出所有的 错误信息 

看似没问题,好,现在不用php内置了,直接用php普通的,我这里是 /disk1/www/hualinux.com/,现在把ls.php复制过去

cp ls.php /disk1/www/hualinux.com/

在浏览器上直接输入,发现空白,为什么呢,因为shell_exec解释了出错只返null所以我改用

passthru 命令,把代码改为:

ini_set('display_errors',1);            //错误信息 

ini_set('display_startup_errors',1);    //php启动错误信息 

error_reporting(-1);                    //打印出所有的 错误信息 

system("head -3 /var/log/messages",$return_var );

echo "return_var: ";

echo $return_var;

?>

运行浏览器结果为:

值为1说明有错误

分析:

因为查看php运行的用户

0基础自学linux运维-5.9-如何在php中执行linux命令或脚本_第5张图片
除了主进行,其它都是nginx用户

查看/var/log/messages日志权限

[root@vm76 ~]# ll /var/log/messages                                                                                  -rw-------. 1 root root 701881 7月  24 00:40 /var/log/messages

发现是除了root其它都不能访问,解决方法有以下几种:

方法一:/etc/php-fpm.d/www.conf中设置user = root 和 group = root,权限太大重启不起来。用python写的 某塔Linux面板 可是直接用root运行的啊!不得不说它内心的强大!

方法二:使用shell脚本在脚本写用expect命令切过去

0基础自学linux运维-5.9-如何在php中执行linux命令或脚本_第6张图片

但这样会暴露root密码,不安全,很危险

方法三:使用Ansible API或SaltStack API接口来实现,这样是不是安全多了

0基础自学linux运维-5.9-如何在php中执行linux命令或脚本_第7张图片
Ansible API
0基础自学linux运维-5.9-如何在php中执行linux命令或脚本_第8张图片
salt API

从上图知道ansible api和salt api,编程语言只有python,可以编写python脚本,然后调用它,这里我不详述了。

方法四:给nginx设置sudo权限免密码切换到root,因nginx不能远程登陆,只能本地运行

visudo,在100行插入

nginx ALL=(ALL) NOPASSWD: ALL

:wq退出

添加一个脚本名叫ls.sh,并修改ls.php代码,如下

[root@vm76 hualinux.com]# cat ls.php

$output = shell_exec("sh ls.sh");

echo "

$output
";

?>

[root@vm76 hualinux.com]# cat ls.sh

#!/bin/bash

sudo head -3 /var/log/messages

再次执行,结果如下:

方法四因为没有验证就可以直接执行,有点不太安全,如果php一旦拿到了上传或修改php文件的权限,那么对方做什么都可以了。所以得非常注意。有一些敏感的东西,很重要的东西建议不要直接让php操作,在sudo中禁止它的行为,即使php被攻破也可以降低影响范围。

对于修改类要记录好日志直接发给ELK日志系统,什么用户操作的,登记IP,操作时间,执行了什么命令。最好做一个安全层做一下审计,一些敏感操作需要手工审计。

注意事项:

如果用sudo echo写入数据在脚本中不能用 sudo echo 'xxx'>name.txt 方式,要使用sudo sh -c 'echo "xxx">name.txt'方式,如:

sudo sh -c 'echo `date +%F-%H:%M:%S`>>ha.txt'


关于执行shell或python脚本

php执行sh脚本或python也是使用上面的php命令,sh脚本用sh xxx.sh执行,python脚本用python xxx.py来执行即可

你可能感兴趣的:(0基础自学linux运维-5.9-如何在php中执行linux命令或脚本)