超越终端:Java语言在命令行环境中的无限潜力

news2025/3/2 4:23:40

在这里插入图片描述

🔭 嗨,您好 👋 我是 vnjohn,在互联网企业担任 Java 开发,CSDN 优质创作者
📖 推荐专栏:Spring、MySQL、Nacos、Java,后续其他专栏会持续优化更新迭代
🌲文章所在专栏:Linux
🤔 我当前正在学习微服务领域、云原生领域、消息中间件等架构、原理知识
💬 向我询问任何您想要的东西,ID:vnjohn
🔥觉得博主文章写的还 OK,能够帮助到您的,感谢三连支持博客🙏
😄 代词: vnjohn
⚡ 有趣的事实:音乐、跑步、电影、游戏

目录

  • 前言
  • 实践篇
    • 依赖
    • 建立会话连接
    • 执行命令处理流结果
    • 调用的入口
    • 演示
  • 总结

前言

结合前后端交互来说,为了能够在前端页面上展示出服务器指定目录下所有的包文件(文件由 Jenkins 自动化编译打包后产生)并提供下载 copy 功能

基于 Android、IOS 打包所生成 apk、ipa 文件都会存放在我们的服务器目录中进行备份,然后在 PC 后台可以对我们这些包文件进行版本和规划管理,所以需要实现这样的一个功能

实践篇

依赖

对这部分工作的操作而言,需要引入第三方依赖来进行协同开发,主要是为我们提供 sshd 工具,实现 Linux 主机互连,读取可访问的文件目录

<dependency>
    <groupId>ch.ethz.ganymed</groupId>
    <artifactId>ganymed-ssh2</artifactId>
    <version>build210</version>
</dependency>

建立会话连接

首先需要与 Linux 服务器开启登录会话,建立双方的连接,才能读取到服务器上指定下的目录文件

private static Connection CONN = null;

private static String DEFAULT_CHART = "UTF-8";

private static String HOSTNAME;

private static String USERNAME;

private static String PASSWORD;

@Value("${ssh.hostname:}")
public void setHostname(String name) {
    HOSTNAME = name;
}

@Value("${ssh.username:}")
public void setUsername(String user) {
    USERNAME = user;
}

@Value("${ssh.password:}")
public void setPassword(String pwd) {
    PASSWORD = pwd;
}

@PostConstruct
public void init() {
    // 创建远程连接,默认连接端口为 22,如果不使用默认,可以使用方法 Connection(String hostname, int port)
    CONN = new Connection(HOSTNAME);
    try {
        // 连接远程服务器
        CONN.connect();
        // 使用用户名和密码登录
        CONN.authenticateWithPassword(USERNAME, PASSWORD);
    } catch (IOException e) {
        log.info("主机名:{},用户名:{},密码:{}", HOSTNAME, USERNAME, PASSWORD);
        log.error("连接主机失败,", e);
    }
}

以上呈现的两个知识点:

@Value 注解构造 static 静态变量的问题,如果将 @Value 注解直接放在属性的上面是无法生效的,如:

@Value("${ssh.hostname}")
private static String hostname;

加上 static 修饰是不会生效的,正确写法是:

@Value("${ssh.hostname}")
public void setHostname(String name) {
	hostname = name;
}

主机名、用户名、密码最好是采用加密的方式进行处理,保存在配置文件中,然后在这块建立连接的时候通过加密算法进行相对应的解密,以确保账号信息不外泄,保证数据安全性

执行命令处理流结果

/**
 * 当前所要执行的命令
 *
 * @param cmd 命令指令
 * @return 执行命令 返回结果
 */
public static String execute(String cmd) {
    String result = "";
    Session session = null;
    try {
        if (CONN != null) {
            // 打开一个会话
            session = CONN.openSession();
            // 执行命令
            session.execCommand(cmd);
            result = processStdout(session.getStdout(), DEFAULT_CHART);
            log.info("执行的命令:{}", cmd);
        }
        return result;
    } catch (IOException e) {
        log.info("执行命令失败,链接 conn:{},执行的命令:{},执行后的结果:{}", CONN, cmd, e.getMessage());
        e.printStackTrace();
        return "执行失败";
    } finally {
        if (session != null) {
            session.close();
        }
    }
}

/**
 * 执行命令返回的结果(返回结果需要等待所有结果返回完毕才返回)
 *
 * @param in      流对象
 * @param charset 编码格式
 * @return
 */
private static String processStdout(InputStream in, String charset) {
    InputStream stdout = new StreamGobbler(in);
    StringBuffer buffer = new StringBuffer();
    BufferedReader br = null;
    try {
        br = new BufferedReader(new InputStreamReader(stdout, charset));
        String line;
        while ((line = br.readLine()) != null) {
            buffer.append(line).append("\n");
        }
    } catch (IOException e) {
        log.error("执行命令异常,", e);
    } finally {
        try {
            stdout.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            if (br != null) {
                br.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return buffer.toString();
}

将所要执行的命令,通过前面所建立的会话执行,处理返回在 Linux 执行后返回的输出流结果,格式为一个通道建立好的流对象:ChannelInputStream,我们只要关注处理它返回的结果即可.

可访问的文件目录应该也是要配置好访问权限,每个指定的文件或目录应该由特定的用户进行管理,避免权限过大,对服务器的其他信息进行误操作,影响到服务器全局的安全性

调用的入口

/**
 * 获取指定目录下的所有子目录和文件列表
 *
 * @param cmd       执行的命令
 * @param firstPath 要筛选的父目录
 * @return 可阅览的目录、文件列表
 */
public static List<ServerFile> getFolderAndFile(String cmd, String firstPath) {
    String result = execute(cmd);
    String[] resultArray = result.split("\n");
    String[] newArray = delete(0, resultArray);
    if (newArray.length == 0) {
        return Collections.emptyList();
    }
    List<ServerFile> readResult = Arrays.stream(newArray).map(str -> {
        ServerFile serverFile = new ServerFile();
        // 判断当前行遍历是否是目录级
        boolean flag = str.startsWith("d");
        String fileName = str.substring(str.lastIndexOf(" ") + 1);
        serverFile.setFolderFlag(flag);
        serverFile.setFileName(fileName);
        serverFile.setPath(firstPath + "/" + fileName);
        if (flag) {
            // 如果当前行是目录那么需要继续递归当前方法查找它下面的文件或目录
            List<ServerFile> folderAndFile = getFolderAndFile(cmd + "/" + fileName, serverFile.getPath());
            serverFile.setChildren(folderAndFile);
        }
        return serverFile;
    }).collect(Collectors.toList());
    return readResult;
}

/**
 * 此方法为了删除数组中第一个元素 重构数组并返回,第一行数据为统计数量,故需要进行移除
 * <p>
 * [root@trench android]# ls -l
 * total 0
 * -rw-r--r-- 1 root root 0 Nov  1 10:30 1
 * -rw-r--r-- 1 root root 0 Nov  1 10:30 2
 * </p>
 *
 * @return 返回目录、文件数组
 */
public static String[] delete(int index, String[] array) {
    // 数组的删除其实就是覆盖前一位
    String[] arrNew = new String[array.length - 1];
    for (int i = 0; i < array.length - 1; i++) {
        if (i < index) {
            arrNew[i] = array[i];
        } else {
            arrNew[i] = array[i + 1];
        }
    }
    return arrNew;
}

这是最终由接口或单元测试类调用的方法,传入所要执行的命令以及所要渲染的首路径:所要渲染的目录

演示

在配置中将属性进行传递,hotstname、username、password 三个参数,作为你的虚拟机或真实云服务器上的公网 IP、用户名、密码

创建一个演示目录以及两个空白文件,如下:

[root@trench android]# pwd
/var/android
[root@trench android]# ls -l
total 0
-rw-r--r-- 1 root root 0 Nov  1 10:30 1
-rw-r--r-- 1 root root 0 Nov  1 10:30 2

那我在单元测试内传入的参数,1-执行命令「ls -l」2-所要筛选的路径「/var/android」

执行以后,结果如下:

在这里插入图片描述

在命令行窗口会输出如下内容:

​​在这里插入图片描述

红色框框是输出的内容,输出的目录和文件有特定标识,目录前面会有 一个 d 关键字,输出内容的第一行是总大小,这一行需要被忽略,这是工具类 delete 方法起到的作用

getFolderAndFile 该方法是将命令所查到的目录、文件整理成一个树形菜单,前端显示的时候需要写入一个接口调用这个方法

总结

该篇博文作为一个简单的实践操作,通过 Java 代码操作 Linux 命令行,首先是要依赖一个对应的依赖,然后建立与 Linux 客户端的会话连接,通过该会话来执行命令—查询目录文件,运用的场景:通过 PC 后台管理安卓、IOS 打包好文件,统一规范版本管理,希望这篇博文能够让你借鉴起来运用到其他的场景中

🌟🌟🌟愿你我都能够在寒冬中相互取暖,互相成长,只有不断积累、沉淀自己,后面有机会自然能破冰而行!

博文放在 Linux 专栏里,欢迎订阅,会持续更新!

如果觉得博文不错,关注我 vnjohn,后续会有更多实战、源码、架构干货分享!

推荐专栏:Spring、MySQL,订阅一波不再迷路

大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下文见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1157872.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

为什么要安装防静电门禁闸机

安装防静电门禁闸机可以带来以下几个方面的好处&#xff1a; 防止静电干扰&#xff1a;静电是一种非常危险的物理现象&#xff0c;它可以对电子元器件、电路板和其他敏感设备造成损害&#xff0c;甚至导致设备故障和生产中断。防静电门禁闸机可以有效地防止静电的产生和传导&am…

药监局瑞数6 分析 2023版

网站地址 aHR0cHM6Ly93d3cubm1wYS5nb3YuY24veWFvcGluL3lwamdkdC9pbmRleC5odG1s 清除cookie 选中脚本调试 第一次获取的结果ts 第二次获取的结果是一个294cc83.js&#xff0c;可以固定 第三次获取的结果 content和ts属性每次都要换,还有ts属性一定要和content对应,否则你怎么…

面试算法47:二叉树剪枝

题目 一棵二叉树的所有节点的值要么是0要么是1&#xff0c;请剪除该二叉树中所有节点的值全都是0的子树。例如&#xff0c;在剪除图8.2&#xff08;a&#xff09;中二叉树中所有节点值都为0的子树之后的结果如图8.2&#xff08;b&#xff09;所示。 分析 下面总结什么样的节…

【C++项目实战】基于多设计模式下的同步于异步的日志系统(完整详细)

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;命运给你一个低的起点&#xff0c;是想看你精彩的翻盘&#xff0c;而不是让你自甘堕落&#xff0c;脚下的路虽然难走&#xff0c;但我还能走&#xff0c;比起向阳而生&#xff0c;我更想尝试逆风…

机器人仿真-gazebo学习笔记(4)xacro和传感器添加

1.xacro简介 URDF文件不具备代码复用的特性&#xff08;在上一篇文章也能发现&#xff0c;其实左右轮是极其相似的但还是要单独描述&#xff09;&#xff0c;一个复杂的机器人模型会拥有大量了的传感器和关节组件&#xff0c;这时候使用URDF文件就太难阅读了。精简化、可复用、…

阿里云急了,云服务器老用户优惠价格99元一年!

2023阿里云服务器双11优惠价格99元一年经济型e实例&#xff0c;并且续费不涨价&#xff0c;云服务器ECS-经济型e实例2核2G配置、3M带宽、40G ESSD entry系统盘优惠价99元一年&#xff0c;原价956.64元/年&#xff0c;可用于中小型网站建设、开发测试、小程序或app搭建&#xff…

Cross-Entropy Loss(多分类损失函数)

文章目录 1. 网络输出output&#xff1a;score2. Cross-Entropy Loss(多分类损失函数) 1. 网络输出output&#xff1a;score 2. Cross-Entropy Loss(多分类损失函数) 先用softmax function把score 变成 probabilities。再用交叉熵损失函数来进行Loss的计算

基于深度学习的动物识别 - 卷积神经网络 机器视觉 图像识别 计算机竞赛

文章目录 0 前言1 背景2 算法原理2.1 动物识别方法概况2.2 常用的网络模型2.2.1 B-CNN2.2.2 SSD 3 SSD动物目标检测流程4 实现效果5 部分相关代码5.1 数据预处理5.2 构建卷积神经网络5.3 tensorflow计算图可视化5.4 网络模型训练5.5 对猫狗图像进行2分类 6 最后 0 前言 &#…

基于Amazon Route 53 Resolver 多区域混合 DNS 部署最佳实践

DNS 可为互联网提供域名解析服务&#xff0c;对任何网络应用都十分关键。无论是部署于企业的私有云、公有云还是混合云环境下的 IT 基础设施&#xff0c;通常都会依赖 DNS 记录来完成服务之间或对外的访问。在一个完整的混合云环境中&#xff0c;不仅需要考虑网络层的连通性、可…

查看局域网内另外一个电脑屏幕

查看局域网内另外一个电脑屏幕是一个相对简单但实用的技术。在局域网中&#xff0c;我们可以使用远程桌面、网络发现和共享、软件等技术来实现这一目标。 今天重点讲解一下&#xff0c;如何通过域之盾软件来查看另一个电脑屏幕&#xff1a; 1、部署软件&#xff0c;安装提示一…

【前端系列】Element-UI 悟道

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

基于orangepi lts 3 的延时摄影程序

利用orangepi 摄像头 使用python写一个延时摄影的程序。 一&#xff0c;思路 orangepi 外接摄像头&#xff0c;利用opencv&#xff0c;按照一定间隔取图&#xff0c;再利用opencv 将图片编码成视频。 利用mqtt进行通讯&#xff0c;可以写一个app进行控制。 二&#xff0c;代…

layui form表单 label和input宽度

情况是这样的&#xff0c;表单里有多个输入框&#xff0c;只有个别label 是长的&#xff0c;我就想调整一下个别长的&#xff0c;其它不变 <div class"layui-form-item"><label class"layui-form-label">是否分标分量:</label><div …

计算机毕业设计选题推荐-校园失物招领微信小程序/安卓APP-项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

没搞错吧?阿里云99元一年服务器老用户可以买!

阿里云老用户优惠服务器99元/年&#xff0c;谁再说阿里云不好我给谁急&#xff0c;云服务器ECS配置为经济型e实例&#xff0c;2核CPU、2G内存、3M固定带宽、40G ESSD entry 系统盘&#xff0c;老用户优惠价99元一年&#xff0c;老用户可以买&#xff0c;当然新用户也可以买&…

轻松玩转人物风格迁移!DualStyleGAN让你一键生成各种风格人物图片!【一个有趣的开源项目】

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能AI、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推荐--…

OOM如何处理

1. OOM是什么 OOM是Out of Memory的缩写&#xff0c;意思是内存溢出。它是指程序在申请内存时&#xff0c;系统可分配的内存已不足&#xff0c;从而导致程序运行失败。 2. OOM发生的一些情况 Java heap space 1.1 解释说明 当堆内存&#xff08;Heap Space&#xff09;没有足…

使用VS2017打包安装程序如何修改默认安装路径

步骤如下&#xff1a; 首先找到安装项目 打开文件系统 点击鼠标右键&#xff0c;view-文件系统。这时打开文件系统 找到Application Folder的属性窗口 修改DefaultLocation的属性 如果想改变默认的安装路径&#xff0c;修改DefaultLocation的属性。 去掉计算机的名称。 完…

2023世界传感器大会即将开启,汉威科技向全球发出邀请

由河南省政府、中国科学技术协会主办&#xff0c;郑州市人民政府、中国仪器仪表学会、河南省工业和信息化厅、河南省科学技术协会承办的“2023世界传感器大会”将于11月5日~7日在郑州国际会展中心举办。 传感器是链接数字世界与物理世界的桥梁&#xff0c;是万物互联、智慧化时…

pytorch复现_NMS

NMS&#xff08;非极大值抑制&#xff09;阈值是用于控制在一组重叠的边界框中保留哪些边界框的参数。当检测或识别算法生成多个边界框可能涵盖相同物体时&#xff0c;NMS用于筛选出最相关的边界框&#xff0c;通常是根据它们的置信度分数。 具体来说&#xff0c;NMS的工作原理…