কীভাবে জাভা থেকে লিনাক্স শেল কমান্ড চাওয়া হয়


93

আমি জাভা থেকে কিছু লিনাক্স কমান্ড বাস্তবায়ন করার চেষ্টা করছি পুনঃনির্দেশ (> &) এবং পাইপ (|) ব্যবহার করে। জাভা কীভাবে আদেশ cshবা bashআদেশ দিতে পারে?

আমি এটি ব্যবহার করার চেষ্টা করেছি:

Process p = Runtime.getRuntime().exec("shell command");

তবে এটি পুনর্নির্দেশগুলি বা পাইপের সাথে সামঞ্জস্যপূর্ণ নয়।


4
catএবং cshএকে অপরের সাথে কিছু করার নেই।
বোম্বে

4
আমি অন্যান্য কমান্ডের জন্য প্রশ্নটি বুঝতে পারি, তবে বিড়ালের জন্য: আপনি কেবল ফাইলটিতে পড়েন না কেন?
আত্মবিশ্বাস

8
প্রত্যেকেই প্রথমবার এই ভুলটি পেয়ে যায় - জাভা এর এক্সিকিউটিউট () কেটি পয়েন্ট হিসাবে দেখায়) কমান্ডটি কার্যকর করতে অন্তর্নিহিত সিস্টেমের শেল ব্যবহার করে না। পুনঃনির্দেশ এবং পাইপিং একটি আসল শেলের বৈশিষ্ট্য এবং জাভার এক্সিকিউট () থেকে পাওয়া যায় না।
স্টিভডি

স্টিভেনডিক: আপনাকে অনেক ধন্যবাদ, পুনঃনির্দেশ এবং পাইপিংয়ের কারণে আমি সমস্যা হচ্ছিলাম!
নেরেক

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

উত্তর:


97

exec আপনার শেলের মধ্যে একটি কমান্ড চালায় না

চেষ্টা করুন

Process p = Runtime.getRuntime().exec(new String[]{"csh","-c","cat /home/narek/pk.txt"});

পরিবর্তে.

সম্পাদনা করুন: আমার সিস্টেমে আমার ক্র্যাশ নেই তাই আমি পরিবর্তে বাশ ব্যবহার করেছি। নিম্নলিখিত আমার জন্য কাজ করে

Process p = Runtime.getRuntime().exec(new String[]{"bash","-c","ls /home/XXX"});

@ নরেক এর জন্যে দুঃখিত. আমি অতিরিক্ত \ " 'দৃশ্যত তারা প্রয়োজন হয় না র সরিয়ে এটি সংশোধন করা হয়েছে আমার সিস্টেমে csh শেল হবে না, কিন্তু এটা ব্যাশ সাথে কাজ
KitsuneYMG

4
অন্যরা যেমন উল্লেখ করেছে যে এটির সিএস বা বাশ থাকা স্বতন্ত্র হওয়া উচিত, তাই না?
নরেক

@ নরেক এটি হওয়া উচিত, তবে আমি জানি না; csh কীভাবে যুক্তিগুলি পরিচালনা করে।
কিটসুনওয়াইএমজি

4
ধন্যবাদ. এটি কাজ করে। আসলে আমি "সিএসএস" এর পরিবর্তে "শ" ব্যবহার করেছি।
ফারশিদ

4
সতর্কতা: এই সমাধানটি সম্ভবত ঝুলন্তর সাধারণ সমস্যার মধ্যে চলে আসবে কারণ আপনি এর আউটপুট এবং ত্রুটির স্ট্রিমগুলি পড়েন নি। উদাহরণস্বরূপ: স্ট্যাকওভারফ্লো
এভেজেনি সার্জিভ

32

স্থানগুলির পরিবর্তে কমান্ড এবং যুক্তিগুলি পৃথক করতে প্রসেসবিল্ডার ব্যবহার করুন। ব্যবহৃত শেল নির্বিশেষে এটি কাজ করা উচিত:

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(final String[] args) throws IOException, InterruptedException {
        //Build command 
        List<String> commands = new ArrayList<String>();
        commands.add("/bin/cat");
        //Add arguments
        commands.add("/home/narek/pk.txt");
        System.out.println(commands);

        //Run macro on target
        ProcessBuilder pb = new ProcessBuilder(commands);
        pb.directory(new File("/home/narek"));
        pb.redirectErrorStream(true);
        Process process = pb.start();

        //Read output
        StringBuilder out = new StringBuilder();
        BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line = null, previous = null;
        while ((line = br.readLine()) != null)
            if (!line.equals(previous)) {
                previous = line;
                out.append(line).append('\n');
                System.out.println(line);
            }

        //Check result
        if (process.waitFor() == 0) {
            System.out.println("Success!");
            System.exit(0);
        }

        //Abnormal termination: Log command parameters and output and throw ExecutionException
        System.err.println(commands);
        System.err.println(out.toString());
        System.exit(1);
    }
}

এমনকি java.util পরে। *; সঠিকভাবে আমদানি করা হয় আমি চালানোর জন্য উপরের উদাহরণ পেতে পারি না।
স্টিভ কে

@ স্টেফান আমি লগিং স্টেটমেন্ট এবং ভেরিয়েবলগুলি মুছে ফেলার জন্য উপরের উদাহরণ কোডটি আপডেট করেছি যা আটকানো কোডের বাইরে ঘোষণা করা হয়েছিল এবং এটি এখন সংকলন ও চালানো উচিত। বিনা দ্বিধায় চেষ্টা করুন এবং আমাকে কীভাবে এটি কার্যকর হয় তা আমাকে জানান।
টিম

15

একটি স্বয়ংসম্পূর্ণ পদ্ধতি তৈরি করতে @ টিমের উদাহরণের উপর ভিত্তি করে:

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;

public class Shell {

    /** Returns null if it failed for some reason.
     */
    public static ArrayList<String> command(final String cmdline,
    final String directory) {
        try {
            Process process = 
                new ProcessBuilder(new String[] {"bash", "-c", cmdline})
                    .redirectErrorStream(true)
                    .directory(new File(directory))
                    .start();

            ArrayList<String> output = new ArrayList<String>();
            BufferedReader br = new BufferedReader(
                new InputStreamReader(process.getInputStream()));
            String line = null;
            while ( (line = br.readLine()) != null )
                output.add(line);

            //There should really be a timeout here.
            if (0 != process.waitFor())
                return null;

            return output;

        } catch (Exception e) {
            //Warning: doing this is no good in high quality applications.
            //Instead, present appropriate error messages to the user.
            //But it's perfectly fine for prototyping.

            return null;
        }
    }

    public static void main(String[] args) {
        test("which bash");

        test("find . -type f -printf '%T@\\\\t%p\\\\n' "
            + "| sort -n | cut -f 2- | "
            + "sed -e 's/ /\\\\\\\\ /g' | xargs ls -halt");

    }

    static void test(String cmdline) {
        ArrayList<String> output = command(cmdline, ".");
        if (null == output)
            System.out.println("\n\n\t\tCOMMAND FAILED: " + cmdline);
        else
            for (String line : output)
                System.out.println(line);

    }
}

(পরীক্ষার উদাহরণটি এমন একটি কমান্ড যা ক্রমানুক্রমিক ক্রমে পুনরাবৃত্তভাবে একটি ডিরেক্টরি এবং এর উপ-ডিরেক্টরিতে সমস্ত ফাইল তালিকাভুক্ত করে ))

যাইহোক, কেউ যদি আমাকে বলতে পারেন যে আমাকে কেন সেখানে দুটি এবং চারটির পরিবর্তে চার এবং আটটি ব্যাকস্ল্যাশ দরকার I আমি কিছু শিখতে পারি। আমি যা গণনা করছি তার থেকেও অব্যাহতভাবে ঘটে যাওয়ার আরও একটি স্তর রয়েছে।

সম্পাদনা: লিনাক্সে কেবল এই একই কোডটি চেষ্টা করে দেখতে পেলাম যে পরীক্ষার কমান্ডে আমার অর্ধেক ব্যাকস্ল্যাশ দরকার! (এটি: দুই এবং চারটির প্রত্যাশিত সংখ্যা)) এখন এটি কেবল অদ্ভুত নয়, এটি একটি বহনযোগ্যতার সমস্যা।


আপনার নিজের প্রশ্নের উত্তর নতুন অংশ হিসাবে জিজ্ঞাসা করা উচিত, আপনার উত্তরের অংশ হিসাবে নয়।
vog

ওএসএক্স / ওরাকল জাভা 8 এ দু'একটি দিয়ে কাজ করে। দেখে মনে হচ্ছে আপনার আসল জাভা পরিবেশে কোনও সমস্যা আছে (যা আপনি প্রকৃতির উল্লেখ করেন না)
TheMadsen
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.