ssh 远程执行脚本(自己总结)

ssh 远程执行脚本(自己总结)

1. 远程执行前台脚本

# 1. 在hadoop113 上创建脚本s1.sh,用cat 和here document 创建并赋予执行权限
cd && cat > s1.sh << 'EOF' && chmod +x s1.sh
read             # 标准输入
echo $REPLY      # 标准输出,REPLY 是read 默认赋值变量
ls nonexistence  # 标准错误输出,ls 不存在的文件
EOF

# 2. 在hadoop112 上通过ssh 执行
ssh hadoop113 './s1.sh'
## 屏幕打印出,假设第一行给read 输入了aaa
# aaa
# aaa
# ls: cannot access nonexistence: No such file or directory

# 3. 结论
## 通过ssh 远程执行脚本,会将远程标准输入、标准输出、标注错误输出连接到ssh 客户端。

2. 远程执行后台脚本

# 1. 在hadoop112 执行
ssh hadoop113 './s1.sh &'
## 结果命令一执行就结束了
## 在hadoop113 上 ps -ef | grep s1.sh 也没结果,证明s1.sh 并没有被执行

# 2. 在hadoop113 上创建脚本s2.sh,用cat 和here document 创建并赋予执行权限
cd && cat > s2.sh << 'EOF' && chmod +x s2.sh
hostname             # 显示主机名
ls -l /dev/std*      # 显示标准输入,标准输出,标准错误输出这三个软连接的数据源
ls -l /proc/self/fd  # 显示文件描述符指向的数据源,文件描述符其实也是软连接
ls nonexistence      # 标准错误输出,ls 不存在的文件
echo "END"
EOF

# 3. 在hadoop112 执行
ssh hadoop113 './s2.sh &'
## 屏幕上显示
# hadoop113
# lrwxrwxrwx 1 root root 15 Mar 23 22:09 /dev/stderr -> /proc/self/fd/2
# lrwxrwxrwx 1 root root 15 Mar 23 22:09 /dev/stdin -> /proc/self/fd/0
# lrwxrwxrwx 1 root root 15 Mar 23 22:09 /dev/stdout -> /proc/self/fd/1
# total 0
# lr-x------ 1 abc abc 64 Mar 26 23:32 0 -> /dev/null
# l-wx------ 1 abc abc 64 Mar 26 23:32 1 -> pipe:[53435]
# l-wx------ 1 abc abc 64 Mar 26 23:32 2 -> pipe:[53436]
# lr-x------ 1 abc abc 64 Mar 26 23:32 3 -> /proc/20135/fd
# END

# 4. 结论
## 通过ssh 将远程脚本通过& 放在后台执行时
## 标准输入指向远程服务器的/dev/null,这也解释了为什么s1.sh 中read 为何不执行
## 标准输出通过pipe 指向了ssh 客户端,所以ls 信息和最后的END 都打印了出来了
## 奇怪的是,标准错误输出虽也指向了pipe,但ls nonexistence 的错误信息并没有出现

3. 远程执行后台建议

# 1. 在hadoop113 上创建脚本s3.sh,用cat 和here document 创建并赋予执行权限
cd && cat > s3.sh << 'EOF' && chmod +x s3.sh
echo "start param1=$1"
while true; do
  case $1 in
    1) echo 111 ;;      # 第一个参数为1,打印111 到标准输出stdout
    2) echo 222 >&2 ;;  # 第一个参数为2,打印222 到标准错误输出stderr
    3) date >&2 ;;      # 第一个参数为3,打印日期到标准错误输出stderr
    *) echo 000 ;;      # 默认打印000 到标准输出stdout
  esac
  sleep 2               # 每间隔两秒输出一次
done
EOF


# 2. 在hadoop112 上执行
## 2.1 执行s3.sh 无参数,默认执行echo 000
ssh hadoop113 './s3.sh &'
### 显示start 后,屏幕每隔2 秒打印一次000,Ctrl+c 后,在hadoop113 上 ps -ef | grep s3.sh 能找到该进程
### 必须Ctrl+c 中断,否则无法输入其他命令,所以建议远程执行后台有标准输出的程序将stdout 重定向

## 2.2 执行s3.sh 1,参数1==1,执行echo 111
ssh hadoop113 './s3.sh 1 &'
### 显示start 后,屏幕每隔2 秒打印一次111,Ctrl+c 后,在hadoop113 上 ps -ef | grep s3.sh 能找到该进程
### 必须Ctrl+c 中断,否则无法输入其他命令,所以建议远程执行后台有标准输出的程序将stdout 重定向

## 2.3 执行s3.sh 2,参数1==2,执行echo 222 >&2,等价于echo 222 1>&2
ssh hadoop113 './s3.sh 2 &'
### 屏幕显示start 后直接结束,在hadoop113 上 ps -ef | grep s3.sh 没有结果
### echo 唯一的功能就是输出,而这里让它输出到无效的stderr 上,自然它会报错,导致整个脚本因异常退出

## 2.4 执行s3.sh 3,参数1==3,运行date >&2,等价于date 1>&2
ssh hadoop113 './s3.sh 3 &'
### 屏幕显示start 后阻塞,Ctrl+c 后,在hadoop113 上 ps -ef | grep s3.sh 能找到该进程
### date 比较特殊,即使将它输出到不可用的stderr 也不会报错退出,可能输出并不是它最主要的功能,类似ls >&2 也不报错


# 3. 远程执行后台程序建议
## 3.1 忽略标准输出,屏幕不阻塞
ssh hadoop113 './s3.sh 1 > /dev/null &'
### 不用按Ctrl+c,直接可以输入后续命令

## 3.2 重定向标准输出和标准错误输出到日志文件
ssh hadoop113 './s3.sh 2 > t.log 2>&1 &'
### 这样屏幕不会阻塞,远端的程序也会在后台正常运行,注意2>&1 是一个整体,表示标准错误输出重定向到标准输出
tail -F t.log  # 可查看日志
### tail -F 根据文件名追踪文件,-f 文件滚动后就看不到了,因为虽然文件名相同但后台的inode 信息变更了

参考文章

Linux lsof命令详解
Transferring a file with SSH
SHELL 脚本 – 管道和重定向基础
彻底搞懂shell 的高级I/O 重定向
stderr over ssh -t

发布了27 篇原创文章 · 获赞 4 · 访问量 9686

猜你喜欢

转载自blog.csdn.net/yoshubom/article/details/105130158