রানটাইম.এক্সেক () দিয়ে কীভাবে পাইপগুলি কাজ করবেন?


104

নিম্নলিখিত কোড বিবেচনা করুন:

String commandf = "ls /etc | grep release";

try {

    // Execute the command and wait for it to complete
    Process child = Runtime.getRuntime().exec(commandf);
    child.waitFor();

    // Print the first 16 bytes of its output
    InputStream i = child.getInputStream();
    byte[] b = new byte[16];
    i.read(b, 0, b.length); 
    System.out.println(new String(b));

} catch (IOException e) {
    e.printStackTrace();
    System.exit(-1);
}

প্রোগ্রামটির ফলাফল:

/etc:
adduser.co

আমি যখন শেল থেকে দৌড়ে যাই, অবশ্যই এটি প্রত্যাশার মতো কাজ করে:

poundifdef@parker:~/rabbit_test$ ls /etc | grep release
lsb-release

ইন্টারনেটস আমাকে বলে যে, পাইপের আচরণ ক্রস প্ল্যাটফর্ম নয়, জাভা উত্পাদনকারী জাভা ফ্যাক্টরিতে কাজ করা উজ্জ্বল মনগুলি পাইপগুলির কাজের গ্যারান্টি দিতে পারে না।

কিভাবে আমি এটি করতে পারব?

আমি আমার সমস্ত পার্সিং এর পরিবর্তে জাভা কনস্ট্রাক্টস grepএবং এর পরিবর্তে ব্যবহার করতে যাচ্ছি না sed, কারণ যদি আমি ভাষাটি পরিবর্তন করতে চাই তবে আমি সেই ভাষায় আমার পার্সিং কোডটি পুনরায় লিখতে বাধ্য হব, যা পুরোপুরি কোনও অচল।

শেল কমান্ড কল করার সময় আমি জাভা কীভাবে পাইপিং এবং পুনঃনির্দেশ করতে পারি?


আমি এটি এর মতো দেখতে পাই: আপনি যদি জাভা স্ট্রিং হ্যান্ডলিং দিয়ে এটি করেন তবে সমস্ত প্ল্যাটফর্ম জাভা সমর্থনগুলিতে আপনি জাভা অ্যাপ্লিকেশনটির গ্যারান্টিযুক্ত। ওটিওহ, আপনি যদি শেল কমান্ড দিয়ে এটি করেন তবে জাভা থেকে ল্যাঙ্গেজ পরিবর্তন করা সহজ , তবে আপনি যখন পসিক্স প্ল্যাটফর্মে থাকবেন কেবল তখনই কাজ করবে। অ্যাপ্লিকেশনটি চালু হওয়া প্ল্যাটফর্মের চেয়ে অল্প লোকই অ্যাপ্লিকেশনটির ল্যাঙ্গেজ পরিবর্তন করে। সে কারণেই আমি মনে করি আপনার যুক্তিটি কিছুটা কৌতূহলযুক্ত।
জানুস ট্রয়লসেন

কোনও সাধারণ কিছু নির্দিষ্ট ক্ষেত্রে আপনি জাভাতে নেটিভ ফিল্টারিং command | grep fooচালানো commandএবং চালানোর মাধ্যমে আরও ভাল । এটি আপনার কোডটিকে কিছুটা জটিল করে তোলে তবে আপনি সামগ্রিক সংস্থান ব্যবহার এবং আক্রমণ পৃষ্ঠকে উল্লেখযোগ্যভাবে হ্রাস করেন।
ট্রিপলি

উত্তর:


182

একটি স্ক্রিপ্ট লিখুন, এবং পৃথক কমান্ডের পরিবর্তে স্ক্রিপ্টটি কার্যকর করুন।

পাইপ শেলের একটি অংশ, সুতরাং আপনি এটির মতোও কিছু করতে পারেন:

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

Process p = Runtime.getRuntime().exec(cmd);

@Kaj যদি আপনাকে অপশন যোগ করতে চেয়েছিলেন lsঅর্থাত ls -lrt?
কৌস্তভ দত্ত

8
@ কাজ আমি দেখতে পাচ্ছি যে আপনি শেলটিতে একটি কমান্ডের একটি স্ট্রিং নির্দিষ্ট করতে -c ব্যবহার করার চেষ্টা করছেন, তবে আমি বুঝতে পারছি না কেন আপনাকে কেবল একটি একক স্ট্রিংয়ের পরিবর্তে স্ট্রিং অ্যারে তৈরি করতে হবে?
ডেভিড ডরিয়া

2
যদি কেউ androidএখানে সংস্করণ খুঁজছেন , তবে /system/bin/shপরিবর্তে ব্যবহার করুন
নেক্সেন

25

আমি লিনাক্সে একই ধরণের সমস্যায় পড়েছিলাম, এটি "পিএস-শেফ | গ্রেপ সামপ্রসেসি" বাদে।
কমপক্ষে "ls" দিয়ে আপনার কাছে ভাষা-স্বতন্ত্র (ধীরে ধীরে) জাভা প্রতিস্থাপন রয়েছে। যেমন .:

File f = new File("C:\\");
String[] files = f.listFiles(new File("/home/tihamer"));
for (String file : files) {
    if (file.matches(.*some.*)) { System.out.println(file); }
}

"পিএস" দিয়ে এটি কিছুটা শক্ত, কারণ জাভাতে এটির জন্য কোনও এপিআই নেই বলে মনে হচ্ছে।

আমি শুনেছি সিগার সম্ভবত আমাদের সহায়তা করতে সক্ষম হতে পারে: https://support.hyperic.com/display/SIGAR/Home

তবে সহজ সমাধানটি (কাজ এর দ্বারা নির্দেশিত হিসাবে) হ'ল পাইপযুক্ত কমান্ডটি স্ট্রিং অ্যারে হিসাবে চালিত করা। এখানে পুরো কোডটি রয়েছে:

try {
    String line;
    String[] cmd = { "/bin/sh", "-c", "ps -ef | grep export" };
    Process p = Runtime.getRuntime().exec(cmd);
    BufferedReader in =
            new BufferedReader(new InputStreamReader(p.getInputStream()));
    while ((line = in.readLine()) != null) {
        System.out.println(line); 
    }
    in.close();
} catch (Exception ex) {
    ex.printStackTrace();
}

স্ট্রিং অ্যারেটি পাইপের সাহায্যে কেন কাজ করে, যখন একটি একক স্ট্রিং না ... এটি মহাবিশ্বের অন্যতম রহস্য (বিশেষত যদি আপনি উত্স কোডটি না পড়ে থাকেন)। আমি সন্দেহ করি এটি কারণ কারণ যখন এক্সিকে একক স্ট্রিং দেওয়া হয়, তখন এটি প্রথমে পার্স করে (এমনভাবে যা আমরা পছন্দ করি না)। বিপরীতে, যখন এক্সিকিউটিকে একটি স্ট্রিং অ্যারে দেওয়া হয় তখন এটি পার্সিং না করেই কেবল এটি অপারেটিং সিস্টেমে প্রেরণ করে।

প্রকৃতপক্ষে, আমরা যদি ব্যস্ত দিনের মধ্যে থেকে সময় নিই এবং উত্স কোডটি দেখুন ( http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/ রানটাইম.জাভা # রানটাইম.এক্সেক% 28 জাভা.এলং স্ট্রিং% 2 কেজাভা.এলং স্ট্রিং []% 2Cjava.io.File% 29 ), আমরা দেখতে পাই ঠিক একই ঘটনা ঘটছে:

public Process  [More ...] exec(String command, String[] envp, File dir) 
          throws IOException {
    if (command.length() == 0)
        throw new IllegalArgumentException("Empty command");
    StringTokenizer st = new StringTokenizer(command);
    String[] cmdarray = new String[st.countTokens()];
    for (int i = 0; st.hasMoreTokens(); i++)
        cmdarray[i] = st.nextToken();
    return exec(cmdarray, envp, dir);
}

আমি একই আচরণটি পুনঃনির্দেশ, অর্থাৎ '>' চরিত্রের সাথে দেখছি। স্ট্রিং অ্যারেগুলির এই অতিরিক্ত বিশ্লেষণটি আলোকিত
ক্রিস

আপনার ব্যস্ততার বাইরে আপনার কোনও দিন নেওয়ার দরকার নেই - এটি আপনার চোখের সামনে লেখা আছে ডকস / এপি / জাভা / ল্যাং / রানটাইম এইচটিএমএল # এক্সিকিউটিউট (
জাভা.লং। স্ট্রিং

6

প্রতিটি প্রক্রিয়া চালানোর জন্য একটি রানটাইম তৈরি করুন। প্রথম রানটাইম থেকে আউটপুট স্ট্রিম পান এবং দ্বিতীয়টি থেকে ইনপুট স্ট্রিমে অনুলিপি করুন।


1
এটি একটি ওএস-নেটিভ পাইপের তুলনায় খুব কম দক্ষ এটি উল্লেখ করার মতো, যেহেতু আপনি জাভা প্রক্রিয়াটির ঠিকানা স্পেসে মেমরি অনুলিপি করছেন এবং তারপরে পরবর্তী প্রক্রিয়াতে ফিরে আসবেন।
টিম বউদ্রিউ

0

@ কাজ স্বীকৃত উত্তর লিনাক্সের জন্য। এটি উইন্ডোজের সমতুল্য:

String[] cmd = {
"cmd",
"/C",
"dir /B | findstr /R /C:"release""
};
Process p = Runtime.getRuntime().exec(cmd);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.