java로 shell 명령어 실행하기, pipeline

IT기술/java, spring|2021. 1. 17. 16:19

2020-05-29 작성

 

java로 shell 명령어를 실행하는 방법은 2가지가 있다.
ProcessBuilder와 runtime.exec()를 사용하면 된다.

 

다음은 ProcessBuilder 예제이다. ProcessBuilder에 들어가는 명령어는 String[] 또는 List<String>여야 한다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ProcessBuilderExample {
    public static void main(String[] args) {
        try {
            String[] command = new String[] {"bash","-c", "hdfs dfs -df | tail -n 1"};
            ProcessBuilder processBuilder = new ProcessBuilder(command);
            Process process = processBuilder.start();

            BufferedReader reader =
                    new BufferedReader(new InputStreamReader(process.getInputStream()));

            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }

            int exitCode = process.waitFor();
            System.out.println("\nExited with error code : " + exitCode);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

다음은 runtime.exec() 예제이다. 위와 코드 내용은 2줄 빼고 같다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class RuntimeExecExample {
    public static void main(String[] args) {
        try {
            String[] command = new String[] {"bash","-c", "hdfs dfs -df | tail -n 1"};
            Process process = Runtime.getRuntime().exec(command);

            BufferedReader reader =
                    new BufferedReader(new InputStreamReader(process.getInputStream()));

            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }

            int exitCode = process.waitFor();
            System.out.println("\nExited with error code : " + exitCode);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

명령어에 pipeline이 들어있을 때 실행이 안돼서 많이 헤멨는데,

위의 예제 처럼, shell(sh, bash)명령어 뒤에 pipeline이 있는 명령어를 한번에 써주니, 명령이 잘 실행됐다.

String[] cmd = {
"/bin/sh",
"-c",
"ls /etc | grep release"
};

 

참고사이트:
https://d2.naver.com/helloworld/1113548
https://mkyong.com/java/java-processbuilder-examples/
https://mkyong.com/java/how-to-execute-shell-command-from-java/
http://zetcode.com/java/processbuilder/
https://stackoverflow.com/questions/5928225/how-to-make-pipes-work-with-runtime-exec

댓글()

java spring ip가 특정 ip 대역(cidr)에 속하는 지 확인하기 ip restrict

IT기술/java, spring|2021. 1. 16. 00:14

2020-01-07 작성

 

ip가 특정 ip 대역에 속하는 지 확인해보려고 할때,

누가 만들어 놓은 함수들이 없다면 생각보다 계산이 복잡하다. (내가 만들고 싶지 않다)

 

이런 계산을 왜 하냐면, 망 분리 등 보안 이슈에 대응하기 위해서다.

예를들어 다운로드는 분리된 망안에서만 가능하게 한다던지,

특정 IP만 접속 가능한 페이지를 만들던지 하는 식이다.

 

apache httpd를 사용한다면 쉽게 특정 ip를 제한할 수 있다.

하지만 이렇게하면 세세한 설정은 못할 것이다.

<Location>
Order deny,allow
    Deny from all
    Allow from 10.123.115.0/24
</Location>

java에 대해 찾아보면 apache commons의 SubnetUtils를 사용하라는 글들이 많다.

나도 사용하려고 했지만 이상하게도, maven으로부터 가져오지 못했다.

다운로드해서 lib로 넣기엔 귀찮기도 했다. 그래서 maven 문제를 찾다보니 시간을 많이 버렸다.

그러다가 spring security web에 IpAddressMatcher라는 비슷한 함수가 있다는 것을 알게 되었다.

 

사용법은 복붙한다.

import org.springframework.security.web.util.matcher.IpAddressMatcher;
...

private void checkIpMatch() {
    matches("192.168.2.1", "192.168.2.1"); // true
    matches("192.168.2.1", "192.168.2.0/32"); // false
    matches("192.168.2.5", "192.168.2.0/24"); // true
    matches("92.168.2.1", "fe80:0:0:0:0:0:c0a8:1/120"); // false
    matches("fe80:0:0:0:0:0:c0a8:11", "fe80:0:0:0:0:0:c0a8:1/120"); // true
    matches("fe80:0:0:0:0:0:c0a8:11", "fe80:0:0:0:0:0:c0a8:1/128"); // false
    matches("fe80:0:0:0:0:0:c0a8:11", "192.168.2.0/32"); // false
}

private boolean matches(String ip, String subnet) {
    IpAddressMatcher ipAddressMatcher = new IpAddressMatcher(subnet);
    return ipAddressMatcher.matches(ip);
}

다음은 사용하지는 않았지만, 출처에서 퍼온 light weight solution이다.

/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * Matches a request based on IP Address or subnet mask matching against the remote
 * address.
 * <p>
 * Both IPv6 and IPv4 addresses are supported, but a matcher which is configured with an
 * IPv4 address will never match a request which returns an IPv6 address, and vice-versa.
 *
 * @author Luke Taylor
 * @since 3.0.2
 * 
 * Slightly modified by omidzk to have zero dependency to any frameworks other than the JDK.
 */
public final class IpAddressMatcher {
    private final int nMaskBits;
    private final InetAddress requiredAddress;

    /**
     * Takes a specific IP address or a range specified using the IP/Netmask (e.g.
     * 192.168.1.0/24 or 202.24.0.0/14).
     *
     * @param ipAddress the address or range of addresses from which the request must
     * come.
     */
    public IpAddressMatcher(String ipAddress) {

        if (ipAddress.indexOf('/') > 0) {
            String[] addressAndMask = ipAddress.split("/");
            ipAddress = addressAndMask[0];
            nMaskBits = Integer.parseInt(addressAndMask[1]);
        }
        else {
            nMaskBits = -1;
        }
        requiredAddress = parseAddress(ipAddress);
        assert  (requiredAddress.getAddress().length * 8 >= nMaskBits) :
                String.format("IP address %s is too short for bitmask of length %d",
                        ipAddress, nMaskBits);
    }

    public boolean matches(String address) {
        InetAddress remoteAddress = parseAddress(address);

        if (!requiredAddress.getClass().equals(remoteAddress.getClass())) {
            return false;
        }

        if (nMaskBits < 0) {
            return remoteAddress.equals(requiredAddress);
        }

        byte[] remAddr = remoteAddress.getAddress();
        byte[] reqAddr = requiredAddress.getAddress();

        int nMaskFullBytes = nMaskBits / 8;
        byte finalByte = (byte) (0xFF00 >> (nMaskBits & 0x07));

        // System.out.println("Mask is " + new sun.misc.HexDumpEncoder().encode(mask));

        for (int i = 0; i < nMaskFullBytes; i++) {
            if (remAddr[i] != reqAddr[i]) {
                return false;
            }
        }

        if (finalByte != 0) {
            return (remAddr[nMaskFullBytes] & finalByte) == (reqAddr[nMaskFullBytes] & finalByte);
        }

        return true;
    }

    private InetAddress parseAddress(String address) {
        try {
            return InetAddress.getByName(address);
        }
        catch (UnknownHostException e) {
            throw new IllegalArgumentException("Failed to parse address" + address, e);
        }
    }
}

출처: https://stackoverflow.com/questions/577363/how-to-check-if-an-ip-address-is-from-a-particular-network-netmask-in-java

'IT기술 > java, spring' 카테고리의 다른 글

java로 shell 명령어 실행하기, pipeline  (0) 2021.01.17

댓글()