Java获取Linux上指定文件夹下所有第一级子文件夹

摘要:
转到服务器并查看应用程序日志。计划任务尚未执行。要分析这种情况,首先导出线程转储文件并分析转储文件。发现线程一直在执行sess.execCommand方法,并且线程一直在运行c Wait Here,等待服务器返回信息来唤醒他。问题是,服务器不知道发生了什么,但它没有返回,所以线程一直停留在这里。通常,解决方案可以通过设置超时来解决这些问题。

说明:需要只获得第一级文件夹目录

packagecom.sunsheen.jfids.studio.monitor.utils;

importjava.io.BufferedReader;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.InputStreamReader;
importjava.io.PrintWriter;
importjava.util.ArrayList;
importjava.util.List;

importorg.eclipse.core.runtime.Assert;

importch.ethz.ssh2.ChannelCondition;
importch.ethz.ssh2.Connection;
importch.ethz.ssh2.StreamGobbler;


/*** 遍历出远程服务器上指定目录下的所有文件夹
 * 
 * @authorWangSong
 *
 */
public classGetAllSubfolders {

    privateGetAllSubfolders(){}

    /*** 得到服务器上指定文件夹下所有子文件夹(第一级子文件夹)
     * @return
     */
    public static List<Object>getSubfolderName(String romoteAddr,String username,
            String password,String targetFolder) {
        
        List<Object> folderNameList = new ArrayList<Object>();
        try{
              Connection connection = new Connection(romoteAddr);//创建一个连接实例
              connection.connect();//Now connect
              boolean isAuthenticated = connection.authenticateWithPassword(username, password);//認證
              Assert.isTrue(isAuthenticated, "用戶名或密碼錯誤!");
              ch.ethz.ssh2.Session sess = connection.openSession();//創建一個會話
              sess.requestPTY("bash");
              sess.startShell();
              InputStream stdout = newStreamGobbler(sess.getStdout());
              InputStream stderr = newStreamGobbler(sess.getStderr());
              BufferedReader stdoutReader = new BufferedReader(newInputStreamReader(stdout));
              BufferedReader stderrReader = new BufferedReader(newInputStreamReader(stderr));
              //向服务器上输入命令
              PrintWriter out = newPrintWriter(sess.getStdin());
              out.println("cd " + targetFolder);//進入日志文件存放的目录
              out.println("ls -ld */");
              out.println("exit");
              out.close();
              sess.waitForCondition(ChannelCondition.CLOSED|ChannelCondition.EOF | ChannelCondition.EXIT_STATUS,30000);
              
              //本机查看远程操作的指令及状态
              System.out.println("输入指令后对应的显示信息:");      
              while (true) {
                  String line =stdoutReader.readLine();
                  if (line == null)
                      break;
                  System.out.println(line);
                  //取出文件夹那条记录
                  if(line.contains("drwxr-xr-x")){
                      //取出正确的文件夹名
                      StringBuffer sb = 
                              new StringBuffer(line.substring(line.lastIndexOf(" "),line.lastIndexOf("/")));
                      line = sb.toString().replace(" ", "");
                      folderNameList.add(line); 
                  }
              }
              System.out.println("ExitCode: " +sess.getExitStatus());
              
              //关闭连接
sess.close();
              connection.close();
              stderrReader.close();
              stdoutReader.close();
          } catch(IOException e) {
              e.printStackTrace(System.err);
              System.exit(2);
          }
        returnfolderNameList;
    }

}

上面代码可能会出现线程阻塞(客户端等待服务器应答信息),参考下面方式解决

使用ch.ethz.ssh2中sess.execCommand方法导致线程卡死的原因分析

技术标签:ssh2sess.execCommand线程卡死

背景

前几天有同事反馈,说生产上的定时任务好像卡住了,没有执行。
上服务器,查看应用日志,定时任务确实没有执行。

分析

这种情况,第一时间先把线程dump文件导出来
分析dump文件,发现线程一直在执行sess.execCommand方法

线程现在一直在c.wait这里,等待服务器返回信息将他唤醒。
问题是服务器不知道啥情况,就是不返回,所以线程就一直卡在这里了

解决方案

一般来说可以通过设置超时时间来处理这些问题。但是这个方法根本没有超时时间设置的参数。
好在找到了waitForCondition这个方法,可以设置一些条件来达到超时时间设置的效果.

/**列出目录下的文件信息
*/
public staticString[] getRemoteDirFileNames(Connection conn, String remoteDir){
        Session sess=null;
        try{
            sess =conn.openSession();
            sess.execCommand("ls -lt "+remoteDir);
            InputStream stdout = newStreamGobbler(sess.getStdout());
            InputStream stderr = newStreamGobbler(sess.getStderr());

            byte[] buffer = new byte[100];
            String result = "";
            while (true) {
                if ((stdout.available() == 0)) {
                    int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA |ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 1000*5);
                    if ((conditions & ChannelCondition.TIMEOUT) != 0) {
                        break;//超时后退出循环,要保证超时时间内,脚本可以运行完成
}
                    if ((conditions & ChannelCondition.EOF) != 0) {
                        if ((conditions & (ChannelCondition.STDOUT_DATA |ChannelCondition.STDERR_DATA)) == 0) {
                            break;
                        }
                    }
                }

                if(stdout!=null){
                    String fileNames=ConvertUtil.parse_String(stdout);
                    if(fileNames!=null){
                        return fileNames.split("
");
                    }
                }

                while (stderr.available() > 0) {
                    int len =stderr.read(buffer);
                    if (len > 0){
                        result += new String(buffer, 0, len);
                    }
                }
            }

        } catch(Exception e) {
            log.info("获取指定目录下文件列表失败:"+e.getMessage());
        }finally{
            sess.close();
        }
        return null;
    }

免责声明:文章转载自《Java获取Linux上指定文件夹下所有第一级子文件夹》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇redis哨兵模式阿里云ali-oss图片增加水印下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Linux搭建Java环境(JDK+Tomcat+MySQL)

目录 一、项目环境: 二、安装JDK1.8 三、安装Tomcat8.5 四、安装MySQL数据库 五、配置JAVA项目 一、项目环境: 开发环境 生产环境 测试环境 硬件环境: web服务器:cpu:intel i7,8G内存,金士顿1T固态硬盘,万兆网卡 数据库服务器:cpu:intel i7,8G内存,金士顿1T固态硬盘,万兆网卡...

利用LDAP操作AD域

LDAP操作代码样例  初始化LDAP 目录服务上下文 该例子中,我们使用uid=linly,ou=People,dc=jsoso,dc=net这个账号,链接位于本机8389端口的LDAP服务器(ldap://localhost:8389),认证方式采用simple类型,即用户名/密码方式。 private static void initialConte...

Java Enum枚举 遍历判断 四种方式(包括 Lambda 表达式过滤)

示例代码如下: package com.miracle.luna.lambda; import java.util.Arrays; /** * @Author Miracle Luna * @Date 2019/6/9 23:40 * @Version 1.0 */ public enum AlarmGrade {...

JAVA实现AD验证

package service;import java.util.Hashtable; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.directory.DirContext; import javax.naming.directo...

基于 .NET 的 FluentValidation 验证教程

FluentValidation 是一个基于 .NET 开发的验证框架,开源免费,而且优雅,支持链式操作,易于理解,功能完善,还是可与 MVC5、WebApi2 和 ASP.NET CORE 深度集成,组件内提供十几种常用验证器,可扩展性好,支持自定义验证器,支持本地化多语言。 虽然 FluentValidation 是一个非常强大的验证框架,但针对该框...

MySQL通过自定义函数以及存储过程实现递归查询父级ID

1.存储过程定义  存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后调用不需要再次编译 2.为什么用存储过程实现树结构数据查询父级节点  1、能完成较复杂的运算与判断    2、可编程行强,灵活    3、SQL编程的代码可重复使用    4、预编译机制    5、减少...