最近准备写一个脚本重启远程某个机器上的应用,尝试了几种方法
1.第一种方法:
首先设置一下使得ssh登录不需要密码
#!/bin/bash
ssh root@192.168.161.5<<!
cd /opt/NMS/server/bin
nohup ./Server.sh >/dev/null &
!
这个方法会出现什么结果呢?
会出现上述情况,命令在远端已经执行,但在本地机器上不能终止,如果使用了循环,也不能执行到下一个循环,只能用CTRL+C终止,出现此提示
: command not foundn.conf: line 48:
^C被信号 2 杀死。
改了下脚本
ssh root@192.168.161.5<<!
cd /opt/NMS/server/bin
nohup ./Server.sh >/dev/null 2>&1 &
!
在命令里面增加了 2>&1,这个2>&1的意思是把错误信息输入前一个输入正确信息的文件里,也即是/dev/null
执行了一下,成功解决
虽然解决了,但是什么原因也还没想明白,也许执行的那个startMsgServer.sh是会不断返回错误信息的,导致了终止不了,只能用 CTRL+C去终止,如果有循环,会执行到下一个循环。但是为什么在远程机器的本地执行这个命令却不会有这种情况呢?还有那句XXX,不会分配伪终端也是 一个问题,啥意思?
上面是一种方法,但是在<<!!里面是不可以使用变量赋值的,测试了下,不行。
#!/bin/bash
ssh root@192.168.161.5<<!
time=`date +%Y%m%d`
echo $time
!
结果
输出为空
引用远程机器的变量也是不可以的,如
#!/bin/bash
ssh root@192.168.161.5<<!
time=`date +%Y%m%d`
echo "$time"
echo $HOSTNAME
!
输出
-bash-3.00# ./ssh2.sh
因为 stdin 不是终端,不会分配伪终端。
nmbu-oracle
这里输出的是本地主机的主机名变量
从上面可以看出可以使用本地主机的变量,当然这个变量要经过export声明过,因为执行一个脚本的时候是使用一个子shell去执行的。 测试下
设置test_path变量
-bash-3.00# test_path=/ultrapower/ahao
-bash-3.00# export test_path
-bash-3.00# echo $test_path
/ultrapower/ahao
写成这样
#!/bin/bash
ssh root@192.168.161.5<<!
cd $test_path
pwd
!
输出
-bash-3.00# ./test.sh
因为 stdin 不是终端,不会分配伪终端。
/ultrapower/ahao
这里复习下变量的有效范围和export的作用
- 启动一个shell时,操作系统会分配一块内存给shell使用,这个区域的变量可以让子程序使用
- 利用export功能,可以让变量内容写到上述内存中(环境变量)
- 当加载另一个shell时(即启动子程序,而离开原来的父程序),子shell可以将父shell的环境变量所在的内存导入自己的环境变量区块中
脚本不能export(导出)变量到它的父进程(parent process),或父进程的环境里. 就像我
们学的生物一样,一个子进程可以从父进程里继承但不能去影响父进程.
2.下面也是一种方法,可以使用变量,调用远程的一个脚本去执行那个应用的脚本./startapp.sh
#!/bin/bash
app_user=root
app_path=/opt/NMS
ip="172.16.30.20 172.16.30.81"
for app_ip in $ip
do
ssh -l $app_user $app_ip $app_path/startapp.sh
done
远程机器的脚本
#!/bin/bash
APP_PATH=/opt/NMS/bin
cd $PROBE_PATH
pid=`ps -ef |grep app|grep -v grep|grep -v tail|awk '{print $2}'`
if [ -n "$pid" ]
then
echo "the app is alive"
else
echo "then app is die"
echo "app is starting"
nohup ./app.sh > /dev/null 2>&1 &
fi
这种方法不加2>&1也会出现第一种方法的那种情况。
3.还有一种telnet的脚本
远程重启各个机器上的应用
这种脚本通过实验是可以的
#!/bin/bash
file="/export/app.conf"
for i in `cat $file`
do
app_ip=`echo $i|awk -F: '{print $2}'`
login_user=`echo $i|awk -F: '{print $3}'`
login_passwd=`echo $i|awk -F: '{print $4}'`
root_passwd=`echo $i|awk -F: '{print $5}'`
app_path=`echo $i|awk -F: '{print $6}'`
sleep 2
(
sleep 1
echo "$login_user"
echo "$login_passwd"
sleep 2
echo "su -"
sleep 5
echo "$root_passwd"
sleep 2
echo "cd $app_path"
sleep 2
echo "nohup ./app.sh >/dev/null 2>&1 &"
sleep 3
echo "exit"
echo "exit"
sleep 2
)|telnet $app_ip
done
把机子的的账号,密码都写在了这个文件/export/app.conf,例如这样
广州:192.168.161.5:oracle:oracle:root123:/opt/NMS/bin
但是这种方法也有一个弊端,不能使用if语句去判断是否这个应用是否存在,所以改为不直接重启应用,执行远程机器的一个shell脚本,这个shell脚本加入判断语句,这样比较合适,不知道行不行,试试
测试证明是可以的
在远程的机器写了这个脚本,而在本地的机器去执行这个脚本
#!/bin/bash
pid=`ps -ef |grep app|grep -v grep |grep -v tail|grep -v /bin/sh|awk '{print $2}'`
if [ -n "$pid" ]
then
echo "the app is alive"
else
echo "the app is starting"
nohup ./app.sh >/dev/null 2>&1 &
fi
测试成功,记住$pid要用双引号围起来,不然都为true。