Overview

최근 프로그램적으로 서버에서 서버로 접속하여 특정경로에 있는 파일을 읽거나, 지우는 기능을 개발해야 되는 상황이 발생하였다. 굳이라는 생각이 들지만 여러가지 상황에 의해 기능 개발을 하였고 그 과정에서 기록이 필요하여 남긴다. 보통 scp, ssh 등등 같이 linux, unix 상 터미널로도 접속, 파일전송을 할 수 있다. 또한 Java에서도 pure하게 Keyword를 수행할 수 있지만, 외부라이브러리(JSCH)를 통해 SFTP를 사용하였다.

Usage

#1 Java Runtime사용.

Runtime rt = Runtime.getRuntime();
Process process = rt.exec("rm /tmp/*");


#2 JSCH 사용 #2-1


implementation 'com.jcraft:jsch:0.1.55'

Build.gradle 에서 dependency 추가.

#2-2 리소스 관리 부분

private Session createSession(String username, String password, String host) throws JSchException {
    JSch jsch = new JSch();
    //1
    Session session = jsch.getSession(username, host, SFTP_PORT);
    session.setPassword(password);

    Properties config = new Properties();
    config.put("StrictHostKeyChecking", "no");
    session.setConfig(config);

    session.connect();
    return session;
}

private ChannelSftp createSftpChannel(Session session) throws JSchException {
    //2
    ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
    channelSftp.connect();
    return channelSftp;
}
//3
private void closeResources(Session session, ChannelSftp channelSftp, BufferedReader reader) {
    try {
        if (reader != null) reader.close();
        if (channelSftp != null) channelSftp.disconnect();
        if (session != null) session.disconnect();
    } catch (IOException e) {
        log.error("리소스 해제 중 오류 발생", e);
    }
}
  1. 서버 username, password, host 정보를 정확히 기재한다.
  2. session.openChannel은 타입에 따라 알맞은 Instance를 반환하기 떄문에 필요에 맞는 키워드로 Instance를 사용한다.
  3. Resouce를 잘 관리해주자.(close)


#2-3 사용

public String readFileFromSftp(String username, String password, String host, String filePath, String fileName) {
    Session session = null;
    ChannelSftp channelSftp = null;
    BufferedReader reader = null;
    String xmlStr = "";
    try {
        session = createSession(username, password, host);
        channelSftp = createSftpChannel(session);

        if (channelSftp.isConnected()) {
            log.info("SFTP 연결 성공");
            xmlStr = readAndPrintFile(channelSftp, filePath, fileName);
        } else {
            log.error("SFTP 연결 실패");
        }
        return xmlStr;
    } catch (Exception e) {
        log.error("SFTP 작업 중 오류 발생", e);
    } finally {
        closeResources(session, channelSftp, reader);
    }

    return xmlStr;
}

private String readAndPrintFile(ChannelSftp channelSftp, String filePath, String fileName) throws Exception {
    channelSftp.cd(filePath);
    log.info("현재 디렉토리: {}", channelSftp.pwd());
    log.info("디렉토리 내용: {}", channelSftp.ls(".").stream().toList());
    log.info("디렉토리 내용: {}", channelSftp.ls(".").stream().collect(Collectors.toList()));

    StringBuilder sb = new StringBuilder();
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(channelSftp.get(fileName + ".xml")))) {
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
            sb.append(line);
        }
        return sb.toString();
    }

}

readAndPrintFile Method내 pwd, ls 등 linux Keyword function을 제공한다.

마치며,,,

보통 NAS나 볼륨이 공유된 상황이라 Files.readAllBytes 등의 Method를 사용하여 손쉽게 사용한다. 그리고 또는 AWS의 S3를 사용하기 때문에 위 기술된 SFTP까지 쓰는 케이스는 드물긴하다. 모든 내용은 상황과 여건에 맞게 사용해야된다. 또한 thorw로 처리했지만 try ~ catch blcok을 사용한 Exception처리를 하기 바란다.