ssh和scp是使用远程Linux服务器常用的命令,为了安全起见,他们都没有提供直接指定密码的方法,只能通过手动输入的方式来输入密码。有时需要在脚本当中使用ssh或scp访问远程服务器,就会带来一定的困扰。此时,使用ssh key是一种安全有效的方法,但有时可能没有权限配置ssh key,或者只是临时使用,没有必要配置ssh key,就可以用sshpass命令为其指定密码。

sshpass有下述四种指定密码的方式,其中具体的ssh/scp命令被忽略

1. 直接指定:password为密码

sshpass -p password ssh/scp ...

2. 通过文件指定:password.txt文件的第一行为密码

sshpass -f password.txt ssh/scp ...

3. 通过环境变量指定

export SSHPASS=password
sshpass -e ssh/scp ...

为了方便,也可以将SSHPASS变量加入到bashrc中,避免每次都要手动export。

4. 通过文件描述符指定

例如,在shell中将密码重定向到文件描述符,然后将文件描述符传递给sshpass读取密码

exec 3< password.txt
sshpass -d 3 ssh/scp ...
exec 3<&-

或者在其它语言(例如C或C++)中创建文件描述符

#include<unistd.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<stdio.h>
int main() {
    int fd[2]; // 用于传递密码的文件描述符
    if(pipe(fd) < 0) return 1;
    char *p = (char*)malloc(20);
    sprintf(p, "%d", fd[0]);
    char *argv[] = {
        "sshpass",
        "-d",
        p,
        "ssh",
        "user@remote",
        NULL
    };
    pid_t pid;
    pid = fork();
    if(pid == 0) {
        // 子进程使用上述参数执行sshpass
        execvp(argv[0], argv);
        printf("error\n");
    } else {
        // 父进程写入密码
        write(fd[1], "password\n", 9);
        // 等待子进程结束
        wait(NULL);
        printf("success\n");
        free(p);
    }
    return 0;
}

举例说明:假如需要向192.168.1.100的主机地址上用户名为kedixa,密码为123456的用户主目录传递文件k.txt,则使用sshpass可以写成如下的方式,关于ssh/scp命令的使用此处不多介绍。

sshpass -p 123456 scp k.txt kedixa@192.168.1.100:~/k.txt

在首次连接某个主机的时候,需要进行主机认证,此时使用sshpass可能会出现问题,手动连接一次该主机,再使用sshpass连接即可。通常来说,使用sshpass指定密码的方法很不安全,尤其是使用”sshpass -p password”的方法,会将密码以明文的方式存在bash history中。为了安全起见,首先考虑使用ssh key的方式避免输入密码,其次再考虑以文件或环境变量指定密码的方式使用sshpass指定密码。

1 个评论

回复 shomy 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注