Apa perbedaan antara backticks, sistem, dan exec?

237

Bisakah seseorang tolong saya? Dalam Perl, apa perbedaan antara:

exec "command";

dan

system("command");

dan

print `command`;

Apakah ada cara lain untuk menjalankan perintah shell juga?

rbbond
sumber
8
Hampir merupakan duplikat yang tepat dari stackoverflow.com/questions/797127/… , kecuali bahwa yang ini memiliki exec dan yang lainnya memiliki pipa.
Michael Myers

Jawaban:

268

eksekutif

mengeksekusi perintah dan tidak pernah kembali . Ini seperti returnpernyataan dalam suatu fungsi.

Jika perintah tidak ditemukan execmengembalikan false. Itu tidak pernah mengembalikan true, karena jika perintah itu ditemukan tidak pernah kembali sama sekali. Juga tidak ada gunanya mengembalikan STDOUT, STDERRatau keluar dari status perintah. Anda dapat menemukan dokumentasi tentang itu di perlfunc, karena ini adalah fungsi.

sistem

mengeksekusi perintah dan skrip Perl Anda dilanjutkan setelah perintah selesai.

Nilai kembali adalah status keluar dari perintah. Anda dapat menemukan dokumentasi tentang itu di perlfunc.

backticks

seperti systemmengeksekusi perintah dan skrip perl Anda dilanjutkan setelah perintah selesai.

Berbeda dengan systemnilai kembali adalah STDOUTdari perintah. qx//setara dengan backticks. Anda dapat menemukan dokumentasi tentang itu di perlop, karena tidak seperti systemdan execitu adalah operator.


Cara lain

Apa yang tidak ada di atas adalah cara untuk menjalankan perintah secara tidak sinkron. Itu berarti skrip perl Anda dan perintah Anda berjalan secara bersamaan. Ini bisa dicapai dengan open. Ini memungkinkan Anda untuk membaca STDOUT/ STDERRmenulis STDINdari perintah Anda. Ini tergantung platform.

Ada juga beberapa modul yang dapat memudahkan tugas ini. Ada IPC::Open2dan IPC::Open3dan IPC::Run, serta Win32::Process::Createjika Anda berada di windows.

Ludwig Weinzierl
sumber
1
Saya pikir maksud Anda s / perlcunc / perlfunc / ... juga dokumentasi perlipc sangat mendalam tentang membuka pipa.
ephemient
7
perlcunc, mungkin ini akan menjadi nama panggilan baru saya ;-)
Ludwig Weinzierl
8
Sebagai catatan, backticks dan qx [] juga mengisi $? (nilai pengembalian OS).
jjohn
167

Dalam I penggunaan umum system, open, IPC::Open2, atau IPC::Open3tergantung pada apa yang ingin saya lakukan. The qx//operator, sementara sederhana, terlalu membatasi dalam fungsi untuk menjadi sangat berguna di luar hacks cepat. Saya menemukan openbanyak handier.

system: jalankan perintah dan tunggu sampai kembali

Gunakan systemsaat Anda ingin menjalankan perintah, tidak peduli dengan hasilnya, dan tidak ingin skrip Perl melakukan apa pun hingga perintah selesai.

#doesn't spawn a shell, arguments are passed as they are
system("command", "arg1", "arg2", "arg3");

atau

#spawns a shell, arguments are interpreted by the shell, use only if you
#want the shell to do globbing (e.g. *.txt) for you or you want to redirect
#output
system("command arg1 arg2 arg3");

qx//atau `` : jalankan perintah dan ambil STDOUT-nya

Gunakan qx//saat Anda ingin menjalankan perintah, tangkap apa yang ditulisnya ke STDOUT, dan tidak ingin skrip Perl melakukan apa pun hingga perintah selesai.

#arguments are always processed by the shell

#in list context it returns the output as a list of lines
my @lines = qx/command arg1 arg2 arg3/;

#in scalar context it returns the output as one string
my $output = qx/command arg1 arg2 arg3/;

exec: ganti proses saat ini dengan proses lain.

Gunakan execbersama dengan forkketika Anda ingin menjalankan perintah, tidak peduli tentang hasilnya, dan tidak ingin menunggu untuk kembali. systembenar-benar adil

sub my_system {
    die "could not fork\n" unless defined(my $pid = fork);
    return waitpid $pid, 0 if $pid; #parent waits for child
    exec @_; #replace child with new process
}

Anda mungkin juga ingin membaca waitpiddan perlipcmanual.

open: menjalankan proses dan membuat pipa ke STDIN atau STDERR-nya

Gunakan opensaat Anda ingin menulis data ke STDIN proses atau membaca data dari STDOUT proses (tetapi tidak keduanya sekaligus).

#read from a gzip file as if it were a normal file
open my $read_fh, "-|", "gzip", "-d", $filename
    or die "could not open $filename: $!";

#write to a gzip compressed file as if were a normal file
open my $write_fh, "|-", "gzip", $filename
    or die "could not open $filename: $!";

IPC :: Open2 : menjalankan proses dan membuat pipa untuk STDIN dan STDOUT

Gunakan IPC::Open2saat Anda perlu membaca dan menulis ke STDIN dan STDOUT proses.

use IPC::Open2;

open2 my $out, my $in, "/usr/bin/bc"
    or die "could not run bc";

print $in "5+6\n";

my $answer = <$out>;

IPC :: Open3 : menjalankan proses dan membuat pipa ke STDIN, STDOUT, dan STDERR

gunakan IPC::Open3saat Anda perlu menangkap ketiga pegangan file standar dari proses tersebut. Saya akan menulis sebuah contoh, tetapi kebanyakan berfungsi dengan cara yang sama IPC :: Open2 tidak, tetapi dengan urutan yang sedikit berbeda dengan argumen dan pegangan file ketiga.

Chas. Owens
sumber
Jawabannya sangat informatif dan terkini. Terima kasih @ chas-owens
Jassi
IPC :: Open3 terlalu rendah untuk sebagian besar penggunaan. IPC :: Run3 dan IPC :: Run biasanya jauh lebih sesuai.
ikegami
17

Izinkan saya mengutip manualnya:

exec perldoc () :

Fungsi exec menjalankan perintah sistem dan tidak pernah kembali - gunakan sistem alih-alih exec jika Anda ingin mengembalikannya

sistem perldoc () :

Melakukan hal yang persis sama dengan exec DAFTAR, kecuali bahwa garpu dilakukan terlebih dahulu, dan proses induk menunggu proses anak untuk menyelesaikan.

Berbeda dengan exec dan sistem , backticks tidak memberi Anda nilai pengembalian tetapi STDOUT yang dikumpulkan.

perldoc `String` :

Sebuah string yang (mungkin) diinterpolasi dan kemudian dieksekusi sebagai perintah sistem dengan / bin / sh atau yang setara. Kartu liar shell, pipa, dan pengalihan akan dihormati. Output standar yang dikumpulkan dari perintah dikembalikan ; kesalahan standar tidak terpengaruh.


Alternatif:

Dalam skenario yang lebih kompleks, di mana Anda ingin mengambil STDOUT, STDERR atau kode pengembalian, Anda dapat menggunakan modul standar terkenal seperti IPC :: Open2 dan IPC :: Open3 .

Contoh:

use IPC::Open2;
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'some', 'cmd', 'and', 'args');
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;

Akhirnya, IPC :: Jalankan dari CPAN juga layak untuk dilihat…

Benedikt Waldvogel
sumber
3
Ini tanggapan yang kasar. Anda harus berusaha membantu tanpa kemarahan.
Shane C. Mason
1
Saya pikir dia hanya membuat referensi ke RTFM ol ': P
v3.
tidak dimaksudkan kasar sebenarnya;) dihapus f-kata meskipun, untuk menghindari kesalahpahaman ...
Benedikt Waldvogel
2
Saya tentu tidak menafsirkannya sebagai tidak sopan. Brusque, mungkin, tetapi ini bukan pertanyaan yang sangat cerdas yang membutuhkan jawaban yang bijaksana.
ephemient
11

Apa perbedaan antara backticks Perl ( `) system,, dan exec?

exec -> exec "command"; ,
system -> system("command"); and 
backticks -> print `command`;

exec

execmengeksekusi perintah dan tidak pernah melanjutkan skrip Perl. Ini untuk skrip seperti returnpernyataan untuk fungsi.

Jika perintah tidak ditemukan, execmengembalikan false. Itu tidak pernah mengembalikan true, karena jika perintah ditemukan, itu tidak pernah kembali sama sekali. Juga tidak ada gunanya mengembalikan STDOUT, STDERRatau keluar dari status perintah. Anda dapat menemukan dokumentasi tentang itu di perlfunc , karena ini adalah sebuah fungsi.

Misalnya:

#!/usr/bin/perl
print "Need to start exec command";
my $data2 = exec('ls');
print "Now END exec command";
print "Hello $data2\n\n";

Dalam kode di atas, ada tiga printpernyataan, tetapi karena execmeninggalkan skrip, hanya pernyataan cetak pertama yang dieksekusi. Juga, execoutput perintah tidak ditugaskan ke variabel apa pun.

Di sini, hanya Anda yang hanya mendapatkan output dari printpernyataan pertama dan menjalankan lsperintah pada standar keluar.

system

systemmengeksekusi perintah dan skrip Perl Anda dilanjutkan setelah perintah selesai. Nilai kembali adalah status keluar dari perintah. Anda dapat menemukan dokumentasi tentang hal itu di perlfunc .

Misalnya:

#!/usr/bin/perl
print "Need to start system command";
my $data2 = system('ls');
print "Now END system command";
print "Hello $data2\n\n";

Dalam kode di atas, ada tiga printpernyataan. Saat skrip dilanjutkan setelah systemperintah, ketiga pernyataan cetak dijalankan.

Juga, hasil berjalan system adalah ditugaskan untuk data2, tetapi nilai yang diberikan adalah 0(kode keluar dari ls).

Di sini, Anda mendapatkan output dari printpernyataan pertama , kemudian dari lsperintah, diikuti oleh output dari dua printpernyataan terakhir tentang standar keluar.

backticks ( `)

Seperti system, menyertakan perintah di backticks mengeksekusi perintah itu dan skrip Perl Anda dilanjutkan setelah perintah selesai. Berbeda dengan system, nilai kembali adalah STDOUTdari perintah. qx//setara dengan backticks. Anda dapat menemukan dokumentasi tentang itu di perlop , karena tidak seperti sistem dan exec, itu adalah operator.

Misalnya:

#!/usr/bin/perl
print "Need to start backticks command";
my $data2 = `ls`;
print "Now END system command";
print "Hello $data2\n\n";

Dalam kode di atas, ada tiga printpernyataan dan ketiganya dieksekusi. Output dari lstidak akan langsung keluar standar, tetapi ditugaskan ke variabel data2dan kemudian dicetak oleh pernyataan cetak akhir.

linuxtestside
sumber
Penjelasan terbaik dengan contoh. Terima kasih banyak.
Arslan Anwar
2

Perbedaan antara 'exec' dan 'system' adalah bahwa exec mengganti program Anda saat ini dengan 'command' dan TIDAK PERNAH kembali ke program Anda. sistem, di sisi lain, bercabang dan menjalankan 'perintah' dan mengembalikan Anda status keluar dari 'perintah' ketika selesai dijalankan. Centang kembali menjalankan 'perintah' dan kemudian mengembalikan string yang mewakili standarnya (apa pun yang akan dicetak ke layar)

Anda juga dapat menggunakan popen untuk menjalankan perintah shell dan saya pikir ada modul shell - 'use shell' yang memberi Anda akses transparan ke perintah shell yang umum.

Semoga itu menjelaskannya untuk Anda.

Shane C. Mason
sumber
Mungkin maksud Anda use Shell;( search.cpan.org/dist/Shell/Shell.pm )? Ini tidak banyak dipasang, juga tidak berlaku untuk pertanyaan, saya pikir ...
ephemient
1
Bagian terakhir dari pertanyaannya adalah "apakah ada cara lain untuk menjalankan perintah shell juga" - Shell adalah cara lain untuk menjalankan perintah shell.
Shane C. Mason
2
Dokumen secara khusus menyatakan "Paket ini disertakan sebagai etalase, menggambarkan beberapa fitur Perl. Seharusnya tidak digunakan untuk program produksi. Meskipun menyediakan antarmuka sederhana untuk mendapatkan output standar dari perintah sewenang-wenang, mungkin ada yang lebih baik cara mencapai apa yang Anda butuhkan. "
Chas. Owens
2
Sekali lagi, itu menjawab pertanyaannya tentang 'apakah ada cara lain'
Shane C. Mason
Cara yang buruk dan tidak didukung tidak boleh diberikan tanpa peringatan bahwa itu buruk dan tidak didukung.
Chas. Owens