shell脚本中执行ssh

本文介绍如何使用shell脚本和expect解释器实现SSH的一键登录功能,包括脚本的运行机制、shebang的作用、expect的关键命令及如何设置alias别名。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

公司开发使用docker,每次登陆自己开发机总要输入 ssh user_name@ip_string,然后再确认输入password,手快了还经常会输错。作为一个懒人,肯定要找一个取巧的方式,查看了下ssh命令,由于它要进行一次跟服务器的加密交互,所以没有直接附带密码登陆的选项,只好作罢。

前些天在同事进行技术分享时,看到他竟然只输入了一行命令./test.sh就成功登陆了开发机,甚是惊异,于是回来搜索研究了一下,遂成此文。


shell脚本基础

在编写ssh自动登陆脚本之前,先说一下shell脚本的基础,此基础不是一些语法什么的,网上到处都是,这里总结了一下shell脚本的运行机制~

shell脚本的运行方式

首先要说一下shell的几种启动方式,正是踩了脚本启动的坑,才使用原来十分钟就搞定的脚本,花了两个小时才搞定。同时也使得我们运行shell,知其所以然。

通过文件名执行

shell脚本可以直接通过文件名执行,需要注意的是文件需要执行权限。通过 sudo chmod +x ./file_name.sh 来给文件添加执行权限;

指定脚本解释器来执行文件

我们常用的 sh file_name.sh 就是指定了脚本解释器 /bin/sh来解释执行脚本;常见的脚本解释器还有:/bin/bash等,我们可以使用ls -l /bin/*sh命令来查看当前可用的脚本解释器;

使用. ./file_name或source命令执行脚本

这种方式不会像前两种方式一样fork一个子进程去执行脚本,而是使用当前shell环境执行,用于 .bashrc或者.bash_profile被修改的时候,我们不必重启shell或者重新登录系统,就能使当前的更改生效。

shebang

我们写一个shell脚本时,总是习惯在最前面加上一行 #!/binbash,它就是脚本的shebang,至于为什么叫这么个奇怪的名字,C语言和Unix的开发者丹尼斯·里奇称它为可能是类似于"hash-bang"的英国风描述性文字

贴一段wiki上的解释:

在计算机科学中,Shebang是一个由井号和叹号构成的字符串行,其出现在文本文件的第一行的前两个字符。 在文件中存在Shebang的情况下,类Unix操作系统的程序载入器会分析Shebang后的内容,将这些内容作为解释器指令,并调用该指令,并将载有Shebang的文件路径作为该解释器的参数。

简单的说,它指示了此脚本运行时的解释器,所以,使用文件名直接执行shell脚本时,必须带上shebang; 此外,我们还可以在shebang后面直接附加选项,执行时我们默认使用选项执行;

如 test.shshebang为 #!/bin/sh -x,那我们执行脚本时:

./test.sh hello

相当于:

bin/sh -x ./test.sh hello;

而编写一个ssh自动登陆脚本,需要用到的shebang(解释器)为 /usr/bin/expect;

需要注意的是:在指定脚本解释器来执行脚本时,shebang会被指定的脚本解释器覆盖,即优先使用指定的脚本解释器来执行脚本(习惯性地用sh ./test.sh却提示command not found)


expect解释器

expect是一个能实现自动和交互式任务的解释器,它也能解释常见的shell语法命令,其特色在以下几个命令:

spawn命令:

spawn command命令会fork一个子进程去执行command命令,然后在此子进程中执行后面的命令;

在ssh自动登陆脚本中,我们使用 spawn ssh user_name@ip_str,fork一个子进程执行ssh登陆命令;

expect命令:

expect命令是expect解释器的关键命令,它的一般用法为 expect "string",即期望获取到string字符串,可在在string字符串里使用 * 等通配符;

string与命令行返回的信息匹配后,expect会立刻向下执行脚本;

set timeout命令:

set timeout n命令将expect命令的等待超时时间设置为n秒,在n秒内还没有获取到其期待的命令,expect 为false,脚本会继续向下执行;

send命令:

send命令的一般用法为 send "string",它们会我们平常输入命令一样向命令行输入一条信息,当然不要忘了在string后面添加上 \r 表示输入回车;

interact命令:

interact命令很简单,执行到此命令时,脚本fork的子进程会将操作权交给用户,允许用户与当前shell进行交互;


完成脚本

以下是一个完成版的脚本 test.sh

#!/usr/bin/expect                   // 指定shebang

set timeout 3                       // 设定超时时间为3秒
spawn ssh user_name@172.***.***.*** // fork一个子进程执行ssh命令
expect "*password*"                 // 期待匹配到 'user_name@ip_string's password:' 
send "my_password\r"                // 向命令行输入密码并回车
send "sudo -s\r" 
send "cd /data/logs\r"              // 帮我切换到常用的工作目录
interact                            // 允许用户与命令行交互

执行 sudo chmod +x ./test.sh命令给shell脚本添加执行权限;

运行 ./test.sh命令,一键登陆成功!

简单的几个命令,,搭配起来解决了与命令行的交互问题后,很多复杂的功能也不在话下了~


alias别名

脚本完成了,可是还是有些小瑕疵:

  • 输入./file_name.sh命令太长。。。
  • 只能在脚本目录中才能执行,不然使用绝对路径输出的命令更长。

这里我们想到了linux的alias命令:

alias命令:

alias命令使用方式为 alias alias_name="ori_command",将alias_name设置为ori_command的别名,这样我们输入执行alias_name,就相当于执行了ori_command;

可是,我们会发现,当你关闭当前shell后,再打开一个shell窗口,再使用alias_name,系统提示command not found;

有没有能保持命令的方式呢?编辑bash_profile文件。

bash_profile文件

我们编辑bash_profile文件,此文件会在终端窗口创建的时候首先执行一次,所以可以帮我们再设置一次别名;

执行命令vim ~./bash_profile,在文件内部添加:

alias alias_name="/root_dir/../file_name.sh

保存后,再使用 . ~./bash_profilesource ~./bash_profile 在当前脚本执行一遍设置别名命令,完成设置;

这样,我们无论在哪个目录,只要输入alias_name命令,回车,真正的一键登陆!

来源:http://www.cnblogs.com/zhenbianshu/p/5867440.html

<think>嗯,用户现在想了解shell脚本ssh命令的用法、参数解析以及远程执行命令的示例。首先,我需要回顾一下之前讨论的内容,用户之前问过一个关于Bash脚本参数解析和case结构的例子,现在转向ssh脚本中的使用。结合用户提供的四个引用,我需要整理ssh脚本中的常见用法和参数。 首先,用户提到的引用[1]提到使用-f和-n参数让ssh后台运行,并获取进程号来kill掉,这可能涉及到ssh脚本执行后如何管理进程的问题。引用[2]和[3]展示了如何在远程执行命令脚本,包括传递参数和循环多个IP地址。引用[4]提到了使用-t参数分配伪终端,这对于需要交互式的命令可能有帮助,比如执行基于屏幕的程序。 用户现在需要详细的参数解析、示例以及注意事项。比如,常见的参数如-p指定端口,-i指定密钥,-t分配终端,-f后台运行,-n避免标准输入被占用等。需要分别解释这些参数的作用,并给出在脚本中的使用示例。 然后,用户可能需要知道如何远程执行命令,包括单条命令执行本地脚本、传递变量、处理多行命令等。同时,需要注意执行环境的问题,比如远程主机的shell环境、路径问题,以及如何避免交互式提示,比如使用ssh -T或者重定向输入。 另外,用户可能关心的安全性问题,比如使用密钥认证代替密码,或者在脚本中处理密码的问题。不过用户没有特别提到安全,可能暂时不需要深入,但可以简要提及。 在示例部分,需要给出具体的代码片段,比如循环多个主机执行命令,传递参数,执行本地脚本,处理输出等。还要注意引用中提到的ssh后如何终止进程的方法,可能需要结合nohup或者后台运行。 注意事项方面,需要提到错误处理、超时设置、连接失败的情况,以及如何避免脚本因为某个节点失败而中断,比如使用set +e或者检查返回值。 最后,用户可能还希望了解如何优化命令,比如使用ssh连接复用(ControlMaster),减少连接建立的时间,或者并行执行多个ssh命令以提高效率。 现在需要组织这些内容,分点回答,确保结构清晰,参数解析详细,示例实用,并注意引用之前提到的资料,比如引用中的例子可以作为示例的一部分。同时,用户之前的问题涉及到case语句处理参数,现在转向ssh,可能需要保持回答的连贯性,但当前问题主要集中在ssh本身,所以重点应放在ssh的用法上。 需要确保回答覆盖用户的需求:参数解析、用法、示例、注意事项,可能的相关问题。同时,参考用户提供的引用内容,整合到回答中,比如引用[3]中的循环执行脚本的例子,引用[4]中的-t参数的作用,引用[1]中的后台运行和kill进程的方法。 可能还需要比较不同参数的使用场景,比如什么时候用-t,什么时候用-f,或者如何避免ssh挂起等待输入。例如,执行需要伪终端的命令时使用-t,而需要后台运行时使用-f,但要注意进程管理。 总结,回答的结构应该是: 1. 基本用法:ssh user@host command 2. 常用参数解析:-p, -i, -t, -f, -n等 3. 远程执行命令的几种方式:单命令脚本、变量传递、多行命令 4. 示例:循环执行、传递参数、后台运行 5. 注意事项:环境变量、错误处理、安全建议 6. 相关问题:扩展用法、优化、错误排查 确保每个部分都有具体的例子,并引用提供的参考资料中的例子,比如循环多个主机的例子来自引用[3],使用-t的例子来自引用[4],后台运行和kill进程的例子来自引用[1]。 此外,用户可能对如何在脚本中处理密码输入感兴趣,但通常建议使用密钥认证,所以在注意事项中可以提到使用ssh-keygen和ssh-copy-id来配置免密登录,避免在脚本中硬编码密码。 最后,检查是否需要提及ssh的返回值处理,比如检查命令是否成功执行,或者捕获远程命令的输出结果,这在脚本中处理错误时很重要。</think>### Shell脚本SSH命令用法详解 #### 一、SSH远程执行命令基础语法 SSH远程执行命令的通用格式为: ```bash ssh [参数] user@host "command" ``` - `user`:远程主机用户名 - `host`:远程主机IP或域名 - `command`:需要执行命令脚本路径 #### 二、核心参数解析 | 参数 | 作用 | 示例 | |------|-----|------| | `-p` | 指定SSH端口 | `ssh -p 2222 user@host` | | `-i` | 指定私钥文件 | `ssh -i ~/.ssh/id_rsa user@host` | | `-t` | 强制分配伪终端(用于交互式命令)[^4] | `ssh -t user@host "vim file"` | | `-f` | 后台运行SSH进程[^1] | `ssh -f user@host "nohup ./test.sh &"` | | `-n` | 重定向输入到`/dev/null`(避免占用标准输入) | `ssh -n user@host "cmd"` | | `-T` | 禁用伪终端分配 | `ssh -T user@host "echo test"` | #### 三、远程执行命令的4种模式 1. **执行单条命令** ```bash ssh user@host "ls -l /tmp" ``` 2. **执行本地脚本文件** ```bash # 将本地脚本传输到远程执行(需注意路径权限) ssh user@host "bash -s" < local_script.sh # 直接执行远程已有脚本 ssh user@host "/path/to/remote_script.sh arg1 arg2" ``` 3. **传递变量参数** ```bash local_var="Hello" ssh user@host "echo $local_var; uname -a" # 变量会在本地先展开 ssh user@host 'echo $local_var' # 使用单引号保持变量在远程解析 ``` 4. **多行命令执行** ```bash ssh user@host <<'EOF' cd /opt/logs grep "ERROR" app.log | wc -l EOF ``` #### 四、生产环境示例 **示例1:批量操作多台主机(参考引用[3])** ```bash #!/bin/bash nodes=("192.168.1.101" "192.168.1.102") user="admin" cmd="/opt/scripts/deploy.sh" for ip in ${nodes[@]}; do echo "==== 正在操作 $ip ====" ssh -p 22 -t $user@$ip "$cmd" done ``` **示例2:后台运行并管理进程(参考引用[1])** ```bash # 启动远程服务 ssh -f -n user@host "nohup java -jar app.jar > /dev/null 2>&1 &" # 停止远程服务 pid=$(ssh user@host "ps -ef | grep app.jar | grep -v grep | awk '{print \$2}'") ssh user@host "kill -9 $pid" ``` #### 五、关键注意事项 1. **环境差异** 远程主机的`PATH`环境变量可能与本地不同,建议使用绝对路径,例如: ```bash ssh user@host "/usr/local/bin/python3 /opt/script.py" ``` 2. **交互式命令处理** 执行需要终端交互的命令时(如`sudo`或`vim`),必须使用`-t`参数: ```bash ssh -t user@host "sudo systemctl restart nginx" ``` 3. **错误处理** 通过检查SSH返回值确保可靠性: ```bash if ssh user@host "systemctl status httpd"; then echo "服务状态检查成功" else echo "连接或命令执行失败" >&2 exit 1 fi ``` 4. **安全建议** - 使用SSH密钥认证代替密码(`ssh-keygen`生成密钥对) - 敏感操作前添加`set -euo pipefail`增强脚本健壮性 #### 六、高级用法扩展 **SSH隧道端口转发** ```bash # 本地端口转发(将远程3306映射到本地13306) ssh -L 13306:localhost:3306 user@db_host ``` **连接复用优化** ```bash # ~/.ssh/config 配置 Host * ControlMaster auto ControlPath ~/.ssh/control-%r@%h:%p ControlPersist 1h ``` [^1]: `-f`参数使SSH进入后台,适用于长时间任务 [^3]: 批量操作需注意循环结构和错误中断处理 [^4]: `-t`参数强制分配伪终端,支持交互式命令
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值