Perl'in backticks, system ve exec arasındaki fark nedir?


237

Birisi bana yardım edebilir mi? Perl'de, arasındaki fark nedir:

exec "command";

ve

system("command");

ve

print `command`;

Kabuk komutlarını çalıştırmanın başka yolları da var mı?


8
Stackoverflow.com/questions/797127/… 'in neredeyse tam bir kopyası, bunun biri exec ve diğerinin boruları olması.
Michael Myers

Yanıtlar:


268

exec

bir komutu yürütür ve asla geri dönmez . returnBir fonksiyondaki bir ifade gibidir .

Komut bulunmazsa execfalse değerini döndürür. Asla true döndürmez, çünkü komut bulunursa hiçbir zaman geri dönmez. Dönen hiçbir noktası bulunmaktadır STDOUT, STDERRya da komutun çıkış durumunu. perlfuncBir işlev olduğu için bununla ilgili belgeleri bulabilirsiniz .

sistem

bir komut yürütür ve Perl betiğiniz komut bittikten sonra devam eder.

Dönüş değeri, komutun çıkış durumudur. Bununla ilgili belgeleri bulabilirsiniz perlfunc.

backticks

gibi systembir komut yürütür ve perl betiğiniz komut bittikten sonra devam eder.

systemDönüş değerinin aksine STDOUTkomut vardır. qx//ters çentiklere eşdeğerdir. Onunla ilgili belgeleri bulabilirsiniz perlop, çünkü aksine systemve execbir operatördür.


Diğer yollar

Yukarıdakilerden eksik olan bir komutu eşzamansız olarak yürütmenin bir yoludur. Yani perl betiğiniz ve komutunuz aynı anda çalışır. Bu ile başarılabilir open. Komutunuzu okumanıza STDOUT/ STDERRyazmanıza izin verir STDIN. Yine de platforma bağlıdır.

Bu görevleri kolaylaştırabilecek çeşitli modüller de vardır. Orada IPC::Open2ve IPC::Open3ve IPC::Run, hem de Win32::Process::Createpencere üzerinde iseniz.


1
Sanırım s / perlcunc / perlfunc / ... demek de perlipc belgeleri boruları açma konusunda büyük derinliklere gidiyor.
ephemient

7
perlcunc, belki de bu benim yeni takma adım olacak ;-)
Ludwig Weinzierl

8
Kayıt için backticks ve qx [] da $? (OS dönüş değeri).
jjohn

167

Genel Ben Kullanımda system, open, IPC::Open2veya IPC::Open3ne yapmak istediğinize bağlı. qx//Operatör, basit iken, çok hızlı dalaverecileri çok faydalı dışında olma işlevselliği sınırlamakta olduğunu. Çok opendaha kullanışlı buluyorum .

system: bir komut çalıştırın ve geri dönmesini bekleyin

systemBir komutu çalıştırmak istediğinizde kullanın , çıktısını önemsemeyin ve Perl betiğinin komut bitene kadar hiçbir şey yapmasını istemeyin.

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

veya

#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//veya `` : bir komut çalıştırın ve STDOUT'u yakalayın

Kullanım qx//bunu STDOUT yazdıkları, yakalama, bir komutu çalıştırmak istiyor ve Perl kod komutu bitene kadar bir şey yapmak istemiyoruz.

#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: geçerli işlemi başka bir işlemle değiştir.

Bir komutu çalıştırmak istediğinizde execbirlikte kullanın fork, çıktısını önemsemeyin ve geri dönmesini beklemek istemeyin. systemgerçekten sadece

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
}

waitpidVe perlipckılavuzlarını da okumak isteyebilirsiniz .

open: bir işlemi çalıştırın ve STDIN veya STDERR'sine bir boru oluşturun

openBir işlemin STDIN'ine veri yazmak veya bir işlemin STDOUT'undan veri okumak istediğinizde kullanın (ancak her ikisini aynı anda değil).

#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 : bir işlem çalıştırın ve hem STDIN hem de STDOUT için bir boru oluşturun

IPC::Open2Bir işlemin STDIN ve STDOUT öğelerinden okuma ve yazma gerektiğinde kullanın .

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 : bir işlem çalıştırın ve STDIN, STDOUT ve STDERR için bir boru oluşturun

kullanmak IPC::Open3Eğer sürecin her üç standart dosya kolları yakalamak için gerektiğinde. Bir örnek yazmak istiyorum, ancak çoğunlukla IPC :: Open2 ile aynı şekilde çalışır, ancak argümanlar ve üçüncü bir dosya tanıtıcısı için biraz farklı bir düzen ile.


Çok bilgilendirici ve güncel cevap. Thanks @ chas-owens
Jassi

IPC :: Open3 çoğu kullanım için çok düşük seviyededir. IPC :: Run3 ve IPC :: Run genellikle çok daha uygundur.
ikegami

17

Önce kılavuzları alıntılayayım:

perldoc exec () :

Exec fonksiyonu bir sistem komutu yürütür ve asla geri dönmez - eğer geri dönmesini istiyorsanız exec yerine sistemi kullan

perldoc sistemi () :

İlk olarak bir çatal yapılması ve üst işlemin alt işlemin tamamlanmasını beklemesi dışında, exec LIST ile aynı şeyi yapar .

Exec ve sistemin aksine , backticks size dönüş değerini değil toplanan STDOUT'u verir.

perldoc `String` :

(Muhtemelen) enterpolasyonu yapılan ve daha sonra / bin / sh veya eşdeğeri ile sistem komutu olarak yürütülen bir dize . Kabuk joker karakterleri, boruları ve yönlendirmeleri onurlandırılacaktır. Komutun toplanan standart çıktısı döndürülür ; standart hata bundan etkilenmez.


Alternatifler:

STDOUT, STDERR veya dönüş kodunu getirmek istediğiniz daha karmaşık senaryolarda IPC :: Open2 ve IPC :: Open3 gibi iyi bilinen standart modülleri kullanabilirsiniz .

Misal:

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

Son olarak, IPC :: CPAN Run da bakmaya değer…


3
Bu kaba bir yanıt. Öfke olmadan yardım etmeye çalışmalısın.
Shane C. Mason

1
Ben sadece ol 'RTFM: P
v3

aslında kaba değildi;) yanlış anlamaları önlemek için olsa da, f-kelimesini kaldırdı ...
Benedikt Waldvogel

2
Kesinlikle kaba olarak yorumlamadım. Brusque, belki, ama bu düşünceli bir cevap gerektiren son derece akıllı bir soru değil.
ephemient

11

Perl'in backticks ( `) system, ve arasındaki fark nedir exec?

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

exec

execbir komut yürütür ve Perl betiğini sürdürmez. Bu bir betik gibi bir returndeyim gibi bir işlevdir.

Komut bulunamazsa execfalse değerini döndürür. Asla true döndürmez, çünkü komut bulunursa hiçbir zaman geri dönmez. Dönen hiçbir noktası bulunmaktadır STDOUT, STDERRya da komutun çıkış durumunu. Onunla ilgili belgeleri perlfunc'ta bulabilirsiniz , çünkü bu bir işlevdir.

Örneğin:

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

Yukarıdaki kodda, üç printifade vardır, ancak execkomut dosyasını terk ettiği için yalnızca ilk print deyimi yürütülür. Ayrıca, execkomut çıkışı herhangi bir değişkene atanmıyor.

Burada, yalnızca ilk printifadenin çıktısını alıyorsunuz ve standart çıkışta lskomutu yürütüyorsunuz .

system

systembir komut yürütür ve Perl betiğiniz komut bittikten sonra devam eder. Dönüş değeri, komutun çıkış durumudur. Bununla ilgili belgeleri perlfunc'ta bulabilirsiniz .

Örneğin:

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

Yukarıdaki kodda üç printifade vardır. Komuttan sonra komut dosyası kaldığı yerden devam ettiğinden system, üç yazdırma ifadesinin tümü yürütülür.

Aynı zamanda, çalışma sonucu system bir tahsis data2, ancak atanan değer 0(çıkış kodu ls).

Burada, ilk printifadenin çıktısını , ardından lskomutun çıktısını ve ardından printstandart çıkıştaki son iki ifadenin çıktılarını alıyorsunuz .

ters tırnaklar ( `)

Mesela system, bir komutu backticks içine almak o komutu yürütür ve Perl betiğiniz komut bittikten sonra devam eder. Bunun aksine system, dönüş değeri STDOUTkomuttur. qx//ters çentiklere eşdeğerdir. Bununla ilgili belgeleri perlop'ta bulabilirsiniz , çünkü sistemin aksine ve execbir operatördür.

Örneğin:

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

Yukarıdaki kodda, üç printifade vardır ve üçü de yürütülmektedir. Çıktısı lsdoğrudan standart dışı olmayacak, ancak değişkene atanacak data2ve daha sonra son baskı ifadesi ile basılacaktır.


En iyi açıklama örneği. Çok teşekkürler.
Arslan Anwar

2

'Exec' ve 'system' arasındaki fark, exec'in mevcut programınızı 'command' ile değiştirmesi ve ASLA programınıza geri dönmesidir. Diğer yandan sistem, 'command' komutunu çatallar ve çalıştırır ve çalıştırıldığında 'command' komutunun çıkış durumunu döndürür. Arka kene 'command' komutunu çalıştırır ve ardından standart çıkışını temsil eden bir dize döndürür (ekrana ne yazdırırsa yazdırsın)

Kabuk komutlarını çalıştırmak için popen'i de kullanabilirsiniz ve bence bir kabuk modülü var - tipik kabuk komutlarına şeffaf erişim sağlayan 'kabuk kullan'.

Umarım bu sizin için açıklığa kavuşur.


Belki de demek istediniz use Shell;( search.cpan.org/dist/Shell/Shell.pm )? Yaygın olarak yüklü değil, ne de soru için geçerli, sanırım ...
ephemient

1
Sorusunun son kısmı, "kabuk komutlarını çalıştırmanın başka yolları da var mı?" - Shell, kabuk komutlarını çalıştırmanın başka bir yoludur.
Shane C. Mason

2
Dokümanlar özellikle belirtiyor "Bu paket, birkaç Perl özelliğini gösteren bir gösteri örneği olarak dahil edilmiştir. Üretim programları için kullanılmamalıdır. Rasgele komutların standart çıktısını elde etmek için basit bir arayüz sağlamasına rağmen, daha iyi olabilir ihtiyacınız olana ulaşmanın yolları. "
Chas. Owens

2
Yine, 'başka yollar var mı' sorusunu yanıtladı
Shane C. Mason

Kötü ve desteklenmeyen yollar, kötü ve desteklenmediklerine dair uyarı yapılmadan verilmemelidir.
Chas. Owens
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.