>

如果在远程执行 sudo 的过程中报错提示:sudo: no tty present and no askpass program specified

这是因为:sudo will only run a program as a different user if one of these 3 conditions has been met (as far as passwords are concerned):

  • <1>. the NOPASSWD option is specified
  • <2>. the user entered the correct target password
  • <3>. the user entered the correct source password

Since options 2 and 3 require a TTY (sudo won’t read from a pipe) it won’t run if it can’t find one. Check your script if at any point you’re running a script remotely using ssh, as it’s possible that it won’t allocate a TTY for a non-interactive remote command.

执行远程命令的时候, 如果需要在命令行接收用户输入的密码, 那么远程的系统必须要分配一个 TTY 以便用户能输入,如果没法分配,则会报错。

最方便的解决办法是:
在远程机器中 修改 /etc/sudoers 文件, 添加一行 Defaults visiblepw

错误提示: sudo: sorry, you must have a tty to run sudo
解决方法:编辑文件 vi /etc/sudoersDefaults requiretty 这一行注释掉
错误提示:no tty present and no askpass program specified
解决方法:编辑文件 vi /etc/sudoersDefaults visiblepw 这一行加进去
错误提示:Permission denied, please try again.
解决方法:修改/etc/ssh/sshd_configPermitRootLogin 这一行注释解除
但是修改后,出现其他问题,此错误仍会重现 本文链接

参考:http://www.cxybl.com/html/xwzx/20130509/37645.html

在脚本中 ssh 到远程机器执行命令的时候, 无法读取脚本中(相当于本地)定义的变量的值。
比如:
FILENAME=”test.txt”
ssh remote_server echo $FILENAME

将无法显示 $FILENAME 的值

解决办法是: 使用双引号,而不是单引号!
ssh remote_server echo $FILENAME

注意:

  • ssh 中执行连续的多个命令时,命令之间一定要记得用分号; 连接起来!
  • 如果要在 ssh 中定义变量并且引用他, 在引用是一定要记得在 $前面加个 反斜线 \ 做一次转义,否则无法引用。
    比如: 要写成 ssh remote_server “k=99; echo \$k”
    在一键部署的时候, 一般是把 需要部署的主机好填写在一个 txt 文件中, 然后脚本读取这个文件,来分别 scp + ssh 部署。

如果把逐行读取放在外循环, 内循环 ssh 的话, 会导致读取的时候失败!
一个解决办法是: 先读取文件内容到数组变量中, 再遍历这个数组。

读取文件内容到变量有几种方法:
在 bash 4 中, 支持 mapfile, 和 *readarray *两种新命令, 使用方法如下:

readarray myarray < hosts.txt
mapfile -t myarray < hosts.txt

参考:http://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html#index-readarray

如果不是 bash 4, 可以使用如下方法:

IFS=/font>\n' read -d '' -r -a myarray < hosts.txt

打印数组的方法:

echo ${myarray[*]}

或者

for i in ${lines[@]}; do echo $i; done

在 ssh 执行远程命令时, 没法处理 awk '{print $2}' 这种有单引号的命令

解决办法是:
把这种命令写在一个 .sh 脚本里,然后 scp 到远程机器上执行
比如:
scp -oStrictHostKeyChecking=no
awktest.sh remote_server:.
ssh -oStrictHostKeyChecking=no
bash awktest.sh

如果进程存在,就 先 kill 它:
kill $(ps aux | grep ‘[p]ython csp_build.py’ | awk ‘{print $2}’)

这种方式还可以解决很多通过 ssh 命令解决不了的问题!
比如远程登录时可能 shell 不同,ssh 命令中某些命令在不同的 shell 下语法不一样导致不能通用等。

ssh 远程执行解压命令之后,如果解压出来的文件夹的所属用户和组是 1044:1044,需要 chown 命令来改变用户和组信息!

例子:

#!/usr/bin/sh
# -----------------
# 1. 执行 ssh 命令
# 2. 读取本地变量需要加 双引号
# 3. || 后面执行多个语句需要加 ()
# -----------------
FILENAME="aaa.tar.gz"
POSTFIX=".tar.gz"
DEST="/usr/local"
file="hosts.txt"
test -e ../$FILENAME || (echo "$FILENAME not exist"; exit 1)
test -e $file || (echo "$file not exist"; exit 1)
readarray myarray < $file
for i in ${myarray[@]}; do
    scp -oStrictHostKeyChecking=no \
        ../$FILENAME $i:.
    ssh **-oStrictHostKeyChecking=no \
        $USER@$i \
        " \
        echo "host: $i"
        sudo tar zxf $FILENAME -C /usr/local;
        sleep 1s
        "
done