尝试用sshpass解决问题

https://blog.csdn.net/joosonmao/article/details/39160501


sshpass 是开源linux程序

sh登陆不能在命令行中指定密码,sshpass 的出现,解决了这一问题。它允许你用 -p 参数指定明文密码,然后直接登录远程服务器,它支持密码从命令行、文件、环境变量中读取。

源码下载地址:http://sourceforge.net/projects/sshpass/

tar -zxvf sshpass-1.05.tar.gz

cd sshpass-1.05

./configure

make && make install

用lipo -info sshpass查看是arm结构的

顺便说一下,如果用make CC=arm-linux-gcc,编译出来的sshpass用lipo -info sshpass查看是x86_64结构

另外,对于ssh的第一次登陆,会提示:“Are you sure you want to continue connecting (yes/no)”,这时用sshpass会不好使,解决方法:

1.可以在ssh命令后面加上 -o StrictHostKeyChecking=no来解决。比如说上面的命令,就可以写作ssh -p efghi scp [email protected]:/home/xxx/test /root -o StrictHostKeyChecking=no。(这个很重要)

2.或者写入配置文件:把 StrictHostKeyChecking no 加到/etc/ssh/sshconfig 可以让ssh客户端自动接受新主机的hostkey,不用每次都自己输入yes

安装完成后输入sshpass出现如下提示即安装成功:

[root@test ~]# sshpass

Usage: sshpass [-f|-d|-p|-e] [-hV] command parameters

。。。。。。

程序开发:

1、想用程序打包sshpass执行程序运行,但主iOS环境还必须要sshpass才行,所以没有采用这个方法,技术含量不高。

2、将.c导入项目调用,也建立了.h文件,但在调用函数时报为定义的函数,放弃。

3、直接将代码写道需要调用的类里,可以运行,而且还可以掌握sshpass-1.0.5的原理是什么。

    简单说就是通过Fork(),开一个伪终端(复制一个子进程,在子进程里运行需要执行的ssh操作)

下面是相关的资料:

伪终端

1、伪终端看上去像一个终端,但事实上伪终端并不是一个真正的终端。

(1)通常一个进程打开伪终端主设备,然后调用fork。子进程建立了一个新的会话,打开一个相应的伪终端从设备,将其文件描述符复制到标准输入,标准输出和标准出错,然后调用exec。伪终端从设备成为子进程的控制终端。

(2)对于伪终端从设备之上的用户进程来说,其标准输入,标准输出和标准出错都是终端设备,对于这些文件描述符,用户进程能够调用所有输入输出函数。但是因为在伪终端从设备之下并没有真正的终端设备,无意义的函数调用(如改变终端属性)将被忽略。

(3)任何写到伪终端主设备的东西都会作为从设备的输入,反之亦然。事实上所有从设备端的输入都来自于伪终端主设备上的用户进程。这看起来像一个双向管道。但从设备上的终端行规程使我们拥有普通管道没有的其他处理能力。

2、打开伪终端主设备

(1)打开一个可用的伪终端主设备

#include

#include

int posix_openpt(int oflag)

返回值:若成功则返回下一个可用的PTY主设备的文件描述符,若出错则返回-1

参数oflag是一个位屏蔽字,指定如何打开主设备。我们可以指定O_RDWR,要求打开主设备进行读、写,可以指定O_NOCTTY以防止主设备成为调用者的控制终端。其他打开标志都会导致未定义的行为。

(2)设置权限,对单个所有者是读/写,对组所有者是写

#include

int grantpt(int filedes)

若成功则返回0,若出错则返回-1

(3)清除所有的锁标记

#include

int  unlockpt(int filedes)

若成功则返回0,若出错则返回-1

(4)找到从伪终端设备的路径名

#include

char *ptsname(int filedes)

若成功则返回指向PTY从设备名的指针,若出错则返回NULL

int ptym_open(char*pts_name,int pts_namesz)

{

char*ptr;

int fdm;

strncpy(pts_name,"/dev/ptmx",pts_namesz);

pts_name[pts_namesz-1]='\0';

fdm=posix_openpt(O_RDWR);

if(fdm<0)

   return(-1);

if(grantpt(fdm)<0){

    close(fdm);

   return(-2);

}

if(unlockpt(fdm)<0){

    close(fdm);

   return(-3);

}

if((ptr=ptsname(fdm))==NULL){

    close(fdm);

   return(-4);

}

strncpy(pts_name,ptr,pts_namesz);

pts_name[pts_namesz-1]='\0';

return(fdm);

}

3、打开伪终端从设备

int ptys_open(char*pts_name)

{

int fds;

if((fds=open(pts_name,O_RDWR))<0)

   return(-5);

return(fds);

}

4、通常一个进程调用ptym_open来打开一个主设备并且得到从设备的名字,该进程然后以fork分出一个子进程,子进程在调用setsid建立新的会话后调用ptys_open打开从设备,这就是从设备如何成为子进程的控制终端的过程。然后termios和winsize这两个结构在子进程中被初始化。最后从设备的文件描述符被复制到子进程的标准输入,标准输出和标准出错中。这意味着不管子进程以后执行何种程序,它都具有同PTY从设备联系起来的上述三个描述符。在调用完fork后,父进程返回PTY主设备的描述符以及子进程ID。

5、接下来,父进程调用函数loop,该函数仅仅是将从标准输入接受到的所有内容复制到PTY主设备,并将PTY主设备接受到的所有内容复制到标准输出。此实现没有进行中断控制及对错误的忽略。

6、在子进程中执行需在伪终端中执行的程序

int main()

{

pid_t pid;

int fdm;

char slave_name[20];

struct termios orig_termios;

struct winsize size;

pid=pty_fork(&fdm,slave_name,sizeof(slave_name),&orig_termios,&size);

if(pid<0)

    perror("pty_fork");

elseif(pid>0){

    loop(fdm);   

}else{

     char buf[]="himan\n";

    system("ls");

}

exit(0);

}

---------------------

作者:joosonmao

来源:CSDN

原文:https://blog.csdn.net/joosonmao/article/details/39160501

版权声明:本文为博主原创文章,转载请附上博文链接!

你可能感兴趣的:(尝试用sshpass解决问题)