Thực thi kết hợp nhiều lệnh Linux trong một dòng


329

Tôi đang cố gắng hợp nhất nhiều lệnh linux trong một dòng để thực hiện thao tác triển khai. Ví dụ

cd /my_folder
rm *.jar
svn co path to repo
mvn compile package install

Câu trả lời:


716

Nếu bạn muốn thực hiện mỗi lệnh chỉ khi lệnh trước thành công, sau đó kết hợp chúng bằng &&toán tử:

cd /my_folder && rm *.jar && svn co path to repo && mvn compile package install

Nếu một trong các lệnh thất bại, thì tất cả các lệnh khác theo sau nó sẽ không được thực thi.

Nếu bạn muốn thực thi tất cả các lệnh bất kể các lệnh trước có thất bại hay không, hãy tách chúng bằng dấu chấm phẩy:

cd /my_folder; rm *.jar; svn co path to repo; mvn compile package install

Trong trường hợp của bạn, tôi nghĩ rằng bạn muốn trường hợp đầu tiên trong đó việc thực thi lệnh tiếp theo phụ thuộc vào sự thành công của lệnh trước đó.

Bạn cũng có thể đặt tất cả các lệnh trong một tập lệnh và thực hiện thay vào đó:

#! /bin/sh
cd /my_folder \
&& rm *.jar \
&& svn co path to repo \
&& mvn compile package install

(Các dấu gạch chéo ngược ở cuối dòng có ở đó để ngăn shell nghĩ rằng dòng tiếp theo là một lệnh mới; nếu bạn bỏ qua dấu gạch chéo ngược, bạn sẽ cần phải viết toàn bộ lệnh trong một dòng.)

Lưu tệp đó vào một tệp, ví dụ myscript, và làm cho nó có thể thực thi được:

chmod +x myscript

Bây giờ bạn có thể thực thi tập lệnh đó như các chương trình khác trên máy. Nhưng nếu bạn không đặt nó bên trong một thư mục được liệt kê trong PATHbiến môi trường của bạn (ví dụ: /usr/local/binhoặc trên một số bản phân phối Linux ~/bin), thì bạn sẽ cần chỉ định đường dẫn đến tập lệnh đó. Nếu nó trong thư mục hiện tại, bạn thực thi nó với:

./myscript

Các lệnh trong kịch bản hoạt động giống như các lệnh trong ví dụ đầu tiên; lệnh tiếp theo chỉ thực thi nếu lệnh trước thành công. Để thực hiện vô điều kiện tất cả các lệnh, chỉ cần liệt kê từng lệnh trên dòng riêng của nó:

#! /bin/sh
cd /my_folder
rm *.jar
svn co path to repo
mvn compile package install

38
Đối với người đọc trong tương lai: Bạn cũng có thể sử dụng ||thay vì dấu chấm phẩy hoặc &&nếu bạn chỉ muốn lệnh tiếp theo được thực thi nếu lệnh cuối cùng thất bại. Như thử điều này, và nếu nó thất bại, hãy thử nó.
DeVadder

3
Hừm, dấu chấm phẩy không phải lúc nào cũng hoạt động. Ví dụ ls >/dev/null & ; echo $!gây ra lỗi.
Hi-Angel

1
Và điều gì sẽ xảy ra nếu tôi muốn chạy lệnh đầu tiên trong nền và một lệnh khác ở nền trước .. Tôi đang thử lệnh này tail -f my.log & && ./myscriptkhông hoạt động .. vui lòng đề xuất.
OverrockSTAR

4
@Pareshkumar Với bash, bạn có thể làm: { tail -f my.log & } && ./myscriptTuy nhiên, lưu ý rằng việc &&này là vô ích, vì công việc đầu tiên chạy trong nền và do đó công việc thứ hai không thể biết kết quả, vì cả hai công việc sẽ bắt đầu cùng một lúc. Vì vậy, bạn cũng có thể chỉ cần viết:{ tail -f my.log & }; ./myscript
Nikos C.

Nếu tôi cần sudoquyền để chạy một trong các lệnh thì sao? Tôi có nên đặt sudolệnh cầu xin tất cả các lệnh hoặc chỉ trong lệnh cần nó không? Làm thế nào tôi có thể truyền mật khẩu cho lệnh đó để nó được thực thi đúng cách?
Drubio

46

Tôi đã thấy rằng sử dụng; để tách các lệnh chỉ hoạt động ở nền trước. ví dụ :

cmd1; cmd2; cmd3 & - sẽ chỉ thực hiện cmd3trong nền, trong khi cmd1 && cmd2 && cmd3 &- sẽ thực thi toàn bộ chuỗi trong nền NẾU không có lỗi.

Để phục vụ cho việc thực hiện vô điều kiện, sử dụng dấu ngoặc đơn sẽ giải quyết điều này:

(cmd1; cmd2; cmd3) & - sẽ thực thi chuỗi lệnh trong nền, ngay cả khi bất kỳ bước nào thất bại.


1
Là dấu và (trong) trong ví dụ của bạn có chủ ý? Nếu vậy, nó để làm gì?
Technophile

5
@Technophile Đó là chạy lệnh nền
Oak Chantosa

1
Một câu trả lời đơn giản, ngắn gọn và trực tiếp, bạn nên sử dụng các trang web StackExchange thường xuyên hơn là Dean. Cảm ơn vì đầu vào của bạn.
CPHPython

10

Bạn có thể tách các lệnh của mình bằng dấu chấm phẩy:

cd /my_folder;rm *.jar;svn co path to repo;mvn compile package install

Đó có phải là những gì bạn có ý nghĩa?


3

Để chạy tất cả chúng cùng một lúc, bạn có thể sử dụng phím đường ống "|" như vậy

$ cd /my_folder | rm *.jar | svn co path to repo | mvn compile package install

1
Đường ống đang được sử dụng để cung cấp đầu ra của lệnh của bạn cho lệnh tiếp theo làm đầu vào. Ví dụ: X | Đầu ra lệnh Y -> X sẽ hoạt động như đầu vào cho lệnh Y
Arpan Saini

2

Nếu bạn muốn thực thi tất cả các lệnh, cho dù lệnh trước có thực thi hay không, bạn có thể sử dụng dấu chấm phẩy (;) để phân tách các lệnh.

cd /my_folder; rm *.jar; svn co path to repo; mvn compile package install

Nếu bạn chỉ muốn thực hiện lệnh tiếp theo nếu lệnh trước thành công, thì bạn có thể sử dụng && để tách các lệnh.

cd /my_folder && rm *.jar && svn co path to repo && mvn compile package install

Trong trường hợp của bạn, việc thực hiện các lệnh liên tiếp dường như phụ thuộc vào các lệnh trước đó, vì vậy hãy sử dụng ví dụ thứ hai tức là sử dụng && để tham gia các lệnh.


1
cd /my_folder && rm *.jar && svn co path to repo && mvn compile package install

Nó không giống với tập lệnh OP, vui lòng giải thích: nếu lệnh aa thất bại, tập lệnh hủy bỏ
Gilles Quenot

4
Ngoài ra, bạn có thể sử dụng cmd1 || cmd2dấu phân cách nếu bạn chỉ cần cmd2thực thi nếu cmd1trả về trạng thái khác không cho shell và bạn có thể sử dụng cmd1 ; cmd2nếu bạn muốn chạy cả hai lệnh bất kể trạng thái trả về của chúng.
Victor Sorokin

@sputnick Đáng lẽ ra, tôi chỉ cần dán nó vào và nối các lệnh với &&
Mark Stevens

3
@MarkStevens Đó là một triển khai tốt hơn nhưng nó sẽ không đạt được kết quả giống như các lệnh được chạy tuần tự, tôi nghĩ đó là ý nghĩa của sputnick.
andrux

1

Tiện ích của một Ampersand duy nhất là gì? Sáng nay, tôi đã tạo một trình khởi chạy trong bảng XFCE (trong Manjaro + XFCE) để khởi chạy đồng thời 2 trình quản lý mật khẩu:

sh -c "keepassx && password-gorilla"
or
sh -c "keepassx; password-gorilla"

Nhưng nó không hoạt động như tôi muốn. IE, ứng dụng đầu tiên khởi động nhưng ứng dụng thứ hai chỉ bắt đầu khi đóng trước đó

Tuy nhiên, tôi thấy rằng (chỉ có một ký hiệu):

sh -c "keepassx & password-gorilla"

và nó hoạt động như tôi muốn bây giờ ...


1
Ampersand hoạt động như bộ kết thúc lệnh tương tự ;, ngoại trừ việc điều này đặt dấu phẩy trước khi nó ở chế độ nền, tức là shell sẽ không nhìn thấy đầu ra của nó.
Sergiy Kolodyazhnyy

làm việc cho tôi, thx.
DaSqy Stc

-1

Bạn có thể sử dụng như mã sau đây;

cd /my_folder && \
rm *.jar && \
svn co path to repo && \
mvn compile package install

Nó hoạt động ...


-1

Tôi tìm thấy rất nhiều câu trả lời cho loại câu hỏi sai lệch này

Được sửa đổi từ bài đăng này: https://www.webmasterworld.com/linux/3613813.htm

Đoạn mã sau sẽ tạo cửa sổ bash và hoạt động chính xác như cửa sổ bash. Hi vọng điêu nay co ich. Có quá nhiều câu trả lời sai / không hoạt động ngoài kia ...

            Process proc;
            try {
                //create a bash window
                proc = Runtime.getRuntime().exec("/bin/bash");
                if (proc != null) {
                       BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
                       PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())), true);
                       BufferedReader err = new BufferedReader(new InputStreamReader(
                       proc.getErrorStream()));
                       //input into the bash window
                       out.println("cd /my_folder");
                       out.println("rm *.jar");
                       out.println("svn co path to repo");
                       out.println("mvn compile package install");
                       out.println("exit");
                       String line;
                        System.out.println("----printing output-----");
                          while ((line = in.readLine()) != null) {
                             System.out.println(line);
                          }
                          while((line = err.readLine()) != null) {
                             //read errors
                          }
                          proc.waitFor();
                          in.close();
                          out.close();
                          err.close();
                          proc.destroy();
                }

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.