< 返回版块

xzzy 发表于 2023-03-05 18:32

Tags:ssh

想做到类似windows原生ssh命令,现在一点思路也没有。麻烦大佬们指指路!

评论区

写评论
pistachio214 2024-02-28 16:34

功能倒是实现出来了,就是 vim直接寄、tab联想代码没思路

TheBlindM 2023-08-02 16:20

如何异步读写

作者 xzzy 2023-03-08 21:51

大部分问题解决了:

mode.set_boolean(ssh2::PtyModeOpcode::ECHO, false); //关闭回显
mode.set_boolean(ssh2::PtyModeOpcode::IGNCR, true); //忽略输入的回车

但是输出的时候还是会有一个空行...

作者 xzzy 2023-03-08 14:27

根据ssh2的文档和一些例子写了个勉强能跑起来的程序:

#![allow(unused)]
use {
    ssh2::Session,
    std::{
        io::{stdin, stdout, Read, Write},
        net::TcpStream,
        thread,
    },
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut sess = Session::new()?;
    sess.set_tcp_stream(TcpStream::connect("127.0.0.1:22")?);
    sess.handshake()?;
    sess.userauth_password("u0_a36", "123456")?;
    let mut channel = sess.channel_session()?;
    channel.request_pty("xterm", None, None)?;
    channel.shell()?;
    channel.handle_extended_data(ssh2::ExtendedData::Merge)?;
    sess.set_blocking(false);
    let mut ssh_stdin = channel.stream(0);

    let stdin_thread = thread::spawn(move || {
        let mut buf = [0; 1024];
        loop {
            let size = stdin().read(&mut buf).unwrap();
            ssh_stdin.write_all(&buf[..size]).unwrap();
        }
    });
    let stdout_thread = thread::spawn(move || {
        loop {
            let mut buf = [0; 1024];
            match channel.read(&mut buf) {
                Ok(c) if c > 0 => {
                    print!("{}", std::str::from_utf8(&buf).unwrap());
                    stdout().flush().unwrap();
                }
                Ok(0) => break,
                _ => (),
            }
        }
        channel.close().unwrap();
        print!("Exit: {}", channel.exit_status().unwrap());
    });

    stdin_thread.join().unwrap();
    stdout_thread.join().unwrap();
    Ok(())
}

但是运行过程中有问题,向流写入命令后输出的字符不正常,总是会包含命令的回声,例如:

~ $ ls
ls
xxx
xxx
~ $
~ $

望大佬们解解惑!

Snowmanzzz 2023-03-07 11:12

github.com/alexcrichton/ssh2-rs Rust bindings to libssh2, an ssh client library.

廴壬吉 2023-03-06 08:54

chatGPT不实时,这些都是老的代码,现在不一定能运行

作者 xzzy 2023-03-05 21:45
use ssh2::Session;
use std::{
    io::{Read, Write},
    net::TcpStream,
};

fn main() {
    // 连接到 SSH 服务器
    let tcp = TcpStream::connect("127.0.0.1:22").unwrap();
    let mut sess = Session::new().unwrap();
    sess.set_tcp_stream(tcp);
    sess.handshake().unwrap();

    // 身份验证
    sess.userauth_password("a", "123456").unwrap();

    // 创建交互式会话通道
    let mut channel = sess.channel_session().unwrap();
    channel.request_pty("xterm", None, None).unwrap();
    channel.shell().unwrap();

    // 从本地终端读取输入并将其发送到远程终端
    let mut input = String::new();
    loop {
        std::io::stdin().read_line(&mut input).unwrap();
        channel.write_all(input.as_bytes()).unwrap();
        input.clear();

        let mut buffer = [0; 1024];
        let size = channel.read(&mut buffer).unwrap();
        let output = std::str::from_utf8(&buffer[..size]).unwrap();
        print!("{}", output);
    }
}

chatGPT的例子,但是有问题,终端的输出不正常

--
👇
ChenGuoHui: ChatGPT可以给示例代码吗? :)

ChenGuoHui 2023-03-05 20:19

ChatGPT可以给示例代码吗? :)

tch1121 2023-03-05 19:16

ChatGPT回答

如果你想要实现一个类似于Windows原生SSH命令的工具,你可以考虑使用Rust语言来编写。以下是一些实现这个目标的思路和建议: 熟悉SSH协议和其工作原理:在开始编写SSH客户端之前,你需要了解SSH协议和其工作原理。这将有助于你设计和编写代码,并帮助你更好地理解如何使用SSH。 选择SSH库:Rust社区有许多SSH库可供选择,例如russh、ssh2和thrussh等。这些库提供了SSH客户端和服务器的功能,可以帮助你快速地实现SSH客户端。 编写代码:使用选定的SSH库,你可以开始编写代码。你需要定义SSH连接的参数,例如用户名、密码、IP地址、端口等。然后,你可以使用库提供的函数来建立SSH连接,执行命令,上传和下载文件等。 处理错误:处理错误是编写稳健程序的重要部分。你需要确保你的代码能够处理任何可能出现的错误,例如网络连接问题、身份验证失败等。 优化性能:SSH客户端可能需要处理大量数据,因此优化性能也是很重要的。你可以使用Rust提供的并发和异步编程工具来提高程序的效率。 总之,实现类似于Windows原生SSH命令的工具需要你具备一定的Rust编程经验和SSH协议的知识。但是,通过选择合适的SSH库和编写高质量的代码,你可以很快地实现这个目标。

1 共 9 条评论, 1 页