Neden “set” adlı programım yürütülmüyor?


10

Ben böyle basit bir C programı oluşturdum:

int main(int argc, char *argv[]) {

    if (argc != 5) {
       fputs("Not enough arguments!\n", stderr);
       exit(EXIT_FAILURE);
    }

Ve benim PATH vb / bash.bashrc gibi değiştirilmiş var :

PATH=.:$PATH

Bu programı set.c olarak kaydettim ve derliyorum

gcc -o set set.c

klasörde

~/Programming/so

Ancak, aradığımda

set 2 3

hiçbir şey olmuyor. Görünen metin yok.

çağrı

./set 2 3

beklenen sonucu verir

Daha önce PATH ile hiç bir sorun yaşamadım ve

which set

döner ./set. Görünüşe göre PATH doğru olanı. Ne oluyor?


10
'.' Eklemek nispeten tehlikelidir. PATH'nize. Yerel dizinden bir şey yürütürken ./ kullanmak veya yürütülebilir dosyayı ~ / bin /
TREE

7
Test programınızı testtemelde aynı nedenden dolayı çağırmak da kötü bir fikirdir ; testyerleşik bir kabuktur.
Jonathan Leffler

@JonathanLeffler Yine de hızlı testler için bir program çağırmak testmantıklı görünüyor. Tabii ki, içine koyduğunuz PATHzaman gerçekten farklı bir isim bulmalıydınız. Ve programı sizin programınıza PATHyerleştirene kadar ./testyine de onu çağırmanız gerekir . Bu nedenle, testgün sonundan önce silmeyi planladığınız hızlı bir test olduğu sürece bir programın adını kullanmanız bir sakınca yoktur .
kasperd

1
@kasperd: Bildiğim kadarıyla, hızlı bir test programının geleneksel adı foo.
hmakholm Monica

Adını lsverirseniz, var olup olmadığını görmek için her gittiğinizde çalışır (ancak yolunuzu soruda yaptığınız gibi değiştirirseniz).
ctrl-alt-delor

Yanıtlar:


24

Bunun yerine kullanmanın whichhangi bunu en gerektiğinde çalışmaz , kullanım typeEğer bir komut yazın çalıştırılacak ne olacağını belirlemek için:

$ which set
./set
$ type set
set is a shell builtin

Kabuk $PATH, arama yapmadan önce her zaman yerleşikleri arar , bu nedenle ayar $PATHburada yardımcı olmaz.

Yürütülebilir öğenizi başka bir adla yeniden adlandırmak en iyisidir, ancak ödeviniz programın adlandırılmasını gerektiriyorsa setbir kabuk işlevi kullanabilirsiniz:

$ function set { ./set; }
$ type set
set is a function
set ()
{
    ./set
}

(Bu işe yarıyor bash, ancak benzeri mermiler kshbuna izin vermeyebilir. Daha taşınabilir bir çözüm için mikeserv'in cevabına bakın.)

Şimdi yazmak set"set" adlı fonksiyonu çalıştıracak ./set. GNU bashyerleşikleri aramadan önce fonksiyonları arar ve $PATH. Bash man sayfasındaki "COMMAND EXECUTION" adlı bölüm bu konuda daha fazla bilgi verir.

builtinVe üzerindeki belgelere de bakınız.command : help builtinve help command.


3
Sen tavsiye typeüzerine whichama bir neden vermezler. ( Nedenini biliyorum , ama tavsiyeye ihtiyacı olan biri olmaz.)
cjm

1
@cjm İşte neden olmasın üzerine bütün bir inceleme : unix.stackexchange.com/questions/85249/…
Anthony Geoghegan

Çok bilgilendirici. Basit bir görev yapan bu kadar basit bir komut üzerinde o kadar çok tartışma olduğunu asla tahmin edemezsiniz
Ganea Dan Andrei

4
@GaneaDanAndrei Temel olarak, typebunun yerine kullanın which, programınıza "set" adını vermeyin ve bunun function set { ./set; }muhtemelen kaçınmanız gereken çirkin bir hack olduğunu anlayın .
yellowantphil

11

setbash (ve muhtemelen diğer kabukların çoğunda) içinde bir yerleşmedir. Bu, bash işlevi ararken yolu aramayacağı anlamına gelir.

Bir yan açıklama olarak, .güvenlik nedenleriyle yola eklemeye karşı şiddetle tavsiye ediyorum . Örneğin cd, /tmpbaşka bir kullanıcının yürütülebilir bir dosya ekledikten sonra çıktığını düşünün /tmp/cd.


2
Evet, bize hocam kuvvetleri amacıyla ,, bir program" sunmak iken profesyonelce bakmaya değil aptalca bir fikir O notları aşağı yapıldığını değilse..
Ganea Dan Andrei

1
Brownie büyük öğretmenler için puan :(
klimpergeist

4
cdyerleşik bir kabuk olduğundan, örnek, aynı nedenden dolayı çalışmaz set.
Emil Jeřábek

15
Kullanılması ./foobir program çağırmak için ise profesyonel; neden .$ PATH içinde olmaması gerektiğini anladığınızı gösterir . Öğretmeniniz yanlış ve ona bunu söylediğimi söyleyebilirsiniz.
Zwol

10

setdeğil sadece bir yerleşik, bir olan POSIX özel yerleşik . Standartlara belirtilen her şeyden önce bir komut aramasında bulunabilir üzeresiniz birkaç yerleşik komutları vardır - $PATHaranmaması, fonksiyon isimleri aranmaz, vb vardır çoğu builtins değil özel gerçekte olan gerekli POSIX standartlarında olmak Gözlerinde farklı bulundu $PATH önce kendi yerleşik prosedürlerinin herhangi çalışacaktır kabuk. Bu doğrudur echoen diğerleri ve (gerçi bu konuda onur standart geçmişte açık grup posta listelerine de çekişme konusu olmuştur olsun) , ama değil bir set, trap,break ,return, continue, ., :, times, eval, exit, export, readonly, unset, Veya exec.

Bunların tümü kabuğun ayrılmış adlarıdır ve komut arama tercihleri ​​dışında özel özelliklere de sahiptirler. Örneğin, standartlara uygun bir kabukta bu adlardan hiçbiriyle kabuk işlevi tanımlayamazsınız. Bu iyi bir şey - insanların taşınabilir komut dosyaları güvenli bir şekilde yazmalarını sağlar . Bunlar, deneyimli bir senaryo yazarının kendi ortamında güvenli ve güvenilir bir dayanak oluşturabileceği temel komutlardır. Bu ad istila olduğunu değil tavsiye.

Ancak, onu istila etmek istiyorsanız, bunu portatif olarak yapabilirsiniz alias. Kabuk genişletme sırası bu çözümü sağlar. Çünkü aliaskomut değiştirmek ne olursa olsun, okunması esnasında genişletilir settanımın doğru genişleyecektir içinde olan adını, sadece muhtemelen bu isimlerden birine genişletmek olmamalıdır.

Böylece şunları yapabilirsiniz:

alias set=./set

... gayet iyi işliyor.


3

Sorun şu ki set, bir kabuk yerleşik ve en iyi çözüm yürütülebilir programınız için farklı bir ad kullanmak olacaktır .

Bu arada, geçen hafta, aynı ada sahip kabuk yerleşikleri yerine sistem komutlarının nasıl çalıştırılacağı hakkında bir soru sordum ve kabul ettiğim çözüm komutu şu şekilde çalıştırmaktı env:

env set 2 3

Kullanmak istediğiniz komutun geçerli dizininizde bulunduğunu zaten bildiğiniz bu özel durumda, ( .geçerli çalışma dizinini temsil etmek için kullanarak) yolunu girerek yürütülebilir dosyayı doğrudan çalıştırmak daha iyi olur :

./set 2 3

Yukarıdaki çözümlerin her ikisi de kabuk agnostiktir, yani kullandığınız kabuktan bağımsız olarak çalışırlar.

Yuvayı kullanma gibi öneriler commandBash'te çalışmaz: bu yalnızca kabuk işlevlerinin çalışmasını önler . Belgelenmemiş olsa da, kullanmanın commandda kabuk anahtar kelimelerini bastırdığını fark ettim . Ancak, kabuk için aynısını yapmaz builtins gibi set. Anladığım kadarıyla, commandzsh gibi diğer kabuklarla çalışabilir.

Ayrıca, örneğin hile \setya "set"ya 'set'Bash yerleşikleri için işi yok - onlar yerine çalıştırılabilir dosyaları çalıştırmak için de kullanışlıdır olsa takma ad veya kabuk anahtar kelimeler .

Not: Bu cevap ilk olarak Eric'in (kabul edilmiş) cevabı hakkında bir yorum olarak başladı, ancak bir yoruma sığmayacak kadar büyüdü. PATH'ın kullanılmasını typeve eklenmemesini öneren diğer cevaplar .iyidir.

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.