前言
一般运维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官方介绍如下:
建立一个数据
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<<EOF
<?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试下,语法如下:
把ls代码改为
$output = shell_exec("ls -l /disk1/t1");
echo "<pre>$output</pre>";
在浏览器运行一下:
再把 ls -l /disk1/t1 改为查看 c.txt内容
$output = shell_exec("cat /disk1/t1/c.txt");
再按F5刷新一下浏览器查看结果
php权限问题
改为查看/var/log/messages前3行
$output = shell_exec("head -3 /var/log/messages");
为了能在页面显示错误,我在<?php下方添加几行
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 命令,把代码改为:
<?php
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;
?>
运行浏览器结果为:
分析:
因为查看php运行的用户
查看/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命令切过去
但这样会暴露root密码,不安全,很危险
方法三:使用Ansible API或SaltStack 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
<?php
$output = shell_exec("sh ls.sh");
echo "<pre>$output</pre>";
?>
[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来执行即可