Java programming에 대한 질문 입니다.

hyper9의 이미지

제목 부터 어떻게 쓰는게 좋을지 좀 애매하네요 ~
갑자기 Java code쪽을 보는 담당자가 휴가를 가서
제가 봐야하는 처지가 되어 버렸는데요..

Code를 보니, 어디가 문제인지는 알겠는데, 고치는게 어렵네요 ~
그동안 Java code를 한번도 본적이 없었거든요 ㅜㅜ

문제는 java application상에서, 현재 application이 실행되는
platform이 일반 system인지, VMware인지를 판별하는 문제인데요.

C program이나, shell program 처럼 , "dmesg | grep VMware"
을 이용해서 platform이 VMware인지 아닌지를 판별하려고 하거든요.

이럴때, JAVA code로는 어떻게 구현하면 되는지를 모르겠네요.
JAVA를 하시는 분들이 보기에는 어려운 문제가 아닐 것 같아서
질문 올립니다.

조언 주시면 감사하겠습니다.

johan의 이미지

Write Once, Debug Everywhere 문제인가 보군요. 자바 프로그래밍은 안한지 오래되었지만, java operating system information 으로 구글링 해보니 답이라고 생각되는 것이 두번째로 나오네요.

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html

johan의 이미지

VMWare만의 문제라면 java how to detect vmware로 구글링 하면 다음이 걸리네요.

http://stackoverflow.com/questions/154163/detect-virtualized-os-from-an-application

제가 설계했다면 Java property에서 뭔가 api를 제공했을 듯 한데, 그렇지가 않았네요. 그리 바람직한 방법이라고 생각하지 않지만, 방법이 없으면 그거라도 해보셔야 겠죠.

hyper9의 이미지

fp = popen("cat /proc/meminfo | grep MemTotal | awk '{print $2}' | cut -d'k' -f1", "r");
fgets(buff, 10, fp);
이런 방법으로 MemTotal값을 C program으로 읽어 들여서 사용했던적이 있는데요.

Java에서는 이런 경우에 어떻게 처리할까요?
이런 방법을 사용할 수 있다면, "dmesg | grep VMware"를 사용해서, VMware인지 아닌지를
Java program내에서 detect할 수 있다면 쉬울 것 같다는 생각이 들었는데,
이 생각이 Java에는 어울리지 않는 방법인가요?

조언 부탁 드립니다. ~

불편한웹의 이미지

Runtime.getRuntime().exec()
System.getProperties().list()

이것에 대해 알아보시면 될 것 같습니다.
Quote:
이 생각이 Java에는 어울리지 않는 방법인가요?

별 상관은 없는데 시스템에 종속됩니다. 무슨 말인가하면
dmesg | grep 를 넣으면 MS 에서는 작동이 안 되겠죠.
아래처럼 코드를 작성하면 될 것 같네요.
switch(host)
{
    case _MS_: cmd = "어쩌구저쩌구..."; break;
    case _OSX_:
    // ......등등..........
    case _LINUX_: cmd = "dmesg | grep ..."; break;
    default:
}

아..그리고 보안상에 문제가 있을 수 있습니다.

hyper9의 이미지

덕분에 일단은 시작을할 수는 있게 되었습니다 ^^
하지만, 아직도 뭔가 잘 안되네요 ㅜㅜ

제가 해본것은요 ~

private void test_function()
{
   Runtime rt = Runtime.getRuntime();
   Process p = null;
 
   try
   {
       p = rt.exec("dmesg | grem mice");
       BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
 
       String test = null;
       while ((test = in.readLine()) != null)
       {
          print("Test in New Function #1" + test);
       }
       print("Test in New Function #2" + test);
   }
   catch ( Exception e )
   {
       e.printStackTrace();
   }
}

이렇게 해보았는데요, string test에서 찍히는 게 아무것도 없는 것 같아요.
출력값은
Test in New Function #2 null
이렇게 되더라고요.
Test in New Function #1 은 아예 찍히지 않구요.

그럼 test가 null인 것 같은데, dmesg | grep mice 를 linux상에서 해보면
제 system에서는
mice: PS/2 mouse device common for all mice
라고 찍히거든요.
InputStreamReader()사용이 잘못된 걸까요?

이 내용이 위의 Java program에서도 찍히기를 기대한 거였는데,아직 뭔가 문제가
많이 있나보네요 ㅜㅜ

조언 주시면 감사하겠습니다.

lateau의 이미지

p = rt.exec("dmesg | grem mice");

grem으로 되어있는데 설마 테스트해본 소스도 grem으로 되어있는 건 아니겠죠? :)

잡설)
System.getProperties()로 가져올 수 있는 property를 vbox상의 os에서 하나씩 println으로 찍어보니 virtual환경이다라는 내용은 알기 어려울 것 같더군요.
다만 *.seperator, os.name 등으로 실행되고 있는 os의 이름과 종류 정도는 알 수 있겠더군요. 전에 있던 회사에서는 *.seperator로 구분했었습니다. 그닥 정확한 방법은 아닌 것 같지만요.

종속적이 되더라도 os상에서 실행가능한 커맨드로 취득하는 게 정확할 것 같습니다.

--
I think to myself...what a emerging world.

hyper9의 이미지

예,,Test해본 source는 grep으로 되어 있고요.
혹시나 pipe가 문제일까해서..
"dmesg | grep mice" 대신에
"pwd"를 해보았는데, 결과는 마찬가지 인 것 같습니다 ~ ㅜㅜ

lateau의 이미지

음 이상하네요.
올려주신 테스트 코드를 main 메소드로 바꿔서 실행해보니 잘 나옵니다.

import java.lang.System;
import java.io.BufferedReader;
import java.io.InputStreamReader;
 
class Test {
    public static void main(String[] args){
        Runtime rt = Runtime.getRuntime();
        Process p = null;
 
        try {
            p = rt.exec("dmesg");
            BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
 
            String test = null;
            while( ((test = in.readLine()) != null)) {
                System.out.print("Test in New Function #1" + test);
            }
            System.out.print("Test in New Function #2" + test);
        } catch ( Exception e ) {
            e.printStackTrace();
        }
    }
}

결과

Test in New Function #1
Test in New Function #1Thursday 07 January 2010 10:21:19 PM JST
Test in New Function #1Jan  7 21:18:12 studio npe: [ID 236367 kern.info] PCI Express-device: pci8086,3a40@1c, pcieb1
Test in New Function #1Jan  7 21:18:12 studio genunix: [ID 936769 kern.info] pcieb1 is /pci@0,0/pci8086,3a40@1c
Test in New Function #1Jan  7 21:18:12 studio pcplusmp: [ID 805372 kern.info] pcplusmp: pciexclass,060400 (pcieb) instance 2 irq 0x19 vector 0x30 ioapic 0xff intin 0xff is bound to cpu 0
 
...

일단 코드를 실행하고 있는 환경이 좀 궁금하네요.
그럴리는 없겠지만 dmseg를 실행할 권한이 없는 유저로 실행했다거나...(이 경우라면 아마 에러 메세지가 취득될 겁니다)
다른 원인이 있을 수 있겠죠.

그리고 아래 분이 적어주신 ProcessBuilder를 사용하는 편이 좀 더 나을 거라 생각합니다.
일전에 ProcessBuilder를 이용하는 편이 더 좋다는 문서를 읽었던 기억이 납니다. 일 할 때 필요해서 찾아본 문서였는데 회사를 관두는 바람에 문서도 백업 안해두었던 터라 내용이...

dmseg가 문제없이 취득된다면

1. java.util.regex
2. 별도의 쉘 스크립트 작성

두 가지로 필요한 문자열을 탐지해내면 되겠군요. 아마도... :)

--
I think to myself...what a emerging world.

hyper9의 이미지

감사합니다.

지금 이 문제가 기존에 있던 곳에 끼워넣기를 하는 중이라
저도 환경이 어떻다고 얘기해야 할지 잘 모르겠네요 ㅜㅜ

혹시 command가 어떤 권한을로 실행되는 건지, Java code
안에서 확인해 볼 방법은 있을까요?

다시 감사드리면서, 조언도 부탁드립니다 ~ ^^

lateau의 이미지

유저권한의 경우

1. System.getProperties / System.getProperty로 취득이 가능할 것 같네요.

Key  	Description of Associated Value
java.version 	Java Runtime Environment version
java.vendor 	Java Runtime Environment vendor
java.vendor.url 	Java vendor URL
java.home 	Java installation directory
java.vm.specification.version 	Java Virtual Machine specification version
java.vm.specification.vendor 	Java Virtual Machine specification vendor
java.vm.specification.name 	Java Virtual Machine specification name
java.vm.version 	Java Virtual Machine implementation version
java.vm.vendor 	Java Virtual Machine implementation vendor
java.vm.name 	Java Virtual Machine implementation name
java.specification.version 	Java Runtime Environment specification version
java.specification.vendor 	Java Runtime Environment specification vendor
java.specification.name 	Java Runtime Environment specification name
java.class.version 	Java class format version number
java.class.path 	Java class path
java.library.path 	List of paths to search when loading libraries
java.io.tmpdir 	Default temp file path
java.compiler 	Name of JIT compiler to use
java.ext.dirs 	Path of extension directory or directories
os.name 	Operating system name
os.arch 	Operating system architecture
os.version 	Operating system version
file.separator 	File separator ("/" on UNIX)
path.separator 	Path separator (":" on UNIX)
line.separator 	Line separator ("\n" on UNIX)
<span>user.name 	User's account name</span>
<span>user.home 	User's home directory</span>
<span>user.dir 	User's current working directory</span>

화면에 System.getProperty("user.name"); 을 찍어 보시면 실행 중인 유저명을 알 수 있겠네요.

2. $roles user_name 으로 root가 취득되는지 Process나 Runtime으로 exec해보시면 될 것 같습니다.
(리눅스에도 roles 커맨드가 있는지는 확인 안해봤습니다. 혹 비슷한 게 있으면 사용해 보시길 권합니다.)

3. System.getenv("");를 사용해 보세요.
시스템에 선언되어있는 환경변수를 읽어들일 수 있습니다. 단, Deprecated 이므로 테스트 이외에는 사용하시면 안될 것 같네요.

--
I think to myself...what a emerging world.

hyper9의 이미지

앗..뭐가 잘못되었던건지 모르겠네요 ~
암튼 지금은 잘되는걸 확인했습니다.

그리고 pipe가 들어가면 안되는 것 같아요.
그것 때문에 착각을 했던건지도 모르겠습니다.

그리고, pipe를 쓸 수 없었기 때문에, 별도의 shell script를 linux상에서
만들어서 이 shell script가 VMware인지 아닌지를 판별해서 "VMware" 또는 "Linux"
라는 string을 return하도록 했고,

Java Code에서는 p = Runtime.getRuntime().exec("platfrom_check");라고
실행을 해봤습니다.
여기서의 platform_check는 platform이 VMware인지 아닌지를 판별해주는 script이고요.

그리고 아래와 같은 code를 덧붙였습니다.

  if (test.equals("VMware"))
  {
     print("This is VMware");
  }
  else
  {
     print("This is not VMware");
  }

그리고 platform_check가 VMware를 돌려주면
"This is VMware"가 찍히고, 만일 platform_check가 "Linux"라는
값을 돌려주면 "This is not VMware"가 찍히기를 기대했는데,

여기도 문제가 있나봐요.
둘다 안찍히네요 ...

혹시 p.getInputStream()으로 읽어들인 문자열의 끝부분에 \r이나 \n같은게
"VMware"와 같이 만들어낸 string과 달라서 그런걸까요?

아니면,,,어떤 이유에서인지,,조언 부탁드립니다.
감사합니다. ~

lateau의 이미지

파이프가 안 먹히는 건 아마 이 내용 때문인 것 같습니다.

public Process exec(String command)
             throws IOException
 
The command argument is parsed into tokens and then executed as a command in a separate process.

그리고 p.getInputStream 으로 값이 얻어지지 않는 것 같은데 이 부분에 대해선 다음 내용이 의심됩니다.

getInputStream
 
public abstract InputStream getInputStream()
 
Gets the input stream of the subprocess. The stream obtains data piped from the standard output stream of the process represented by this Process object.

shell script에서 return시키는 값을 stdout으로 한 번 바꿔 보신 후 테스트 해보시면 되지 않을까 싶네요. println으로 user 정보와 stream에 들어온 정보도 찍어보시면서 어떤 과정으로 진행되는지 확인해 보시면 좋을 것 같습니다. :)

회사라서 코드를 못돌리는 게 좀 아쉽습니다. 이해를... :)

--
I think to myself...what a emerging world.

dormael의 이미지

p.getErrorStream()으로 반환된 스트림도 찍어보시기 바랍니다.

이 외에도 p.exitValue()의 결과값도 찍어보시면 좋구요.

오래되서 가물가물 하긴 하지만..
Process나 Runtime을 이용해서 우리가 쉘 상에서 쓰는 파이프는 이용할 수 없었던 걸로 기억합니다.

해당 부분을 쉘 스크립트로 만들어서 실행했던 기억이 나는걸로 봐서는요.

오래된 경험이라 지금은 문제 없을수도 있습니다.

이와는 조금 반하는 내용이지만 Java API를 보면 아래와 같은 설명이 있네요.

The ProcessBuilder.start() and Runtime.exec methods create a native process and return an instance of a subclass of Process that can be used to control the process and obtain information about it. The class Process provides methods for performing input from the process, performing output to the process, waiting for the process to complete, checking the exit status of the process, and destroying (killing) the process.

The methods that create processes may not work well for special processes on certain native platforms, such as native windowing processes, daemon processes, Win16/DOS processes on Microsoft Windows, or shell scripts. The created subprocess does not have its own terminal or console. All its standard io (i.e. stdin, stdout, stderr) operations will be redirected to the parent process through three streams (getOutputStream(), getInputStream(), getErrorStream()). The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.

-- Signature --
青い空大好き。
蒼井ソラもっと好き。
파란 하늘 너무 좋아.
아오이 소라 더좋아.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.