Ortam Değişkenleri ve Konumsal Parametreler
$INTEGER
Değişken türlerini tartışmaya başlamadan önce , gerçekte ne olduklarını ve ortam değişkenlerinden nasıl farklı olduklarını anlamamız gerekir. Gibi değişkenler $INTEGER
pozisyon parametreleri olarak adlandırılır. Bu, POSIX (Taşınabilir İşletim Sistemi Arayüzü) standardı, bölüm 2.1'de (vurgu mayın) açıklanmaktadır:
- Kabuk, bir işlevi (bkz. İşlev Tanım Komutu), yerleşik (bkz. Özel Yerleşik Yardımcı Programlar), yürütülebilir dosya veya komut dosyası yürütür ve bağımsız değişkenlerin adlarını 1 ila n numaralı konumsal parametreler olarak verir ve komutun adı (veya komut dosyası içindeki bir işlev durumunda, komut dosyasının adı) 0 numaralı konumsal parametre olarak (bkz. Komut Arama ve Yürütme).
Buna karşılık, $HOME
ve gibi değişkenler$PATH
gibi değişkenler ortam değişkenleridir. Tanımları standardın 8. bölümünde açıklanmıştır :
Bu bölümde tanımlanan ortam değişkenleri çoklu yardımcı programların, işlevlerin ve uygulamaların çalışmasını etkiler. Yalnızca belirli yardımcı programların ilgisini çeken başka ortam değişkenleri de vardır. Yalnızca tek bir yardımcı program için geçerli olan ortam değişkenleri, yardımcı program açıklamasının bir parçası olarak tanımlanır.
Açıklamalarına dikkat edin. Konumsal parametrelerin bir komutun önünde görünmesi amaçlanmıştır, yani command positional_arg_1 positional_arg_2...
. Kullanıcılara komutun özel olarak ne yapması gerektiğini söylemesi sağlanmalıdır. Bunu yaptığınızda echo 'Hello' 'World'
, Hello
ve World
dizeleri yazdırır , çünkü bunlar üzerinde çalışmak echo
istediğiniz şeyler için konumsal parametrelerdir echo
. Veecho
konum parametrelerini yazdırılacak dizeler olarak anlayacak şekilde oluşturulmuştur (isteğe bağlı bayraklardan biri olmadıkça -n
). Bunu farklı bir komutla yaparsanız, ne olduğunu anlamayabilir Hello
veWorld
belki de bir sayı beklemesidir. Konumsal parametrelerin "kalıtsal" olmadığına dikkat edin - bir alt süreç, alt sürece açıkça geçmedikçe üst öğenin konum parametreleri hakkında bilgi sahibi değildir. Genellikle sarmalayıcı komut dosyalarıyla iletilen konumsal parametrelerin görüldüğünü görürsünüz - bir komutun zaten var olan örneğini kontrol eden veya çağrılacak gerçek komuta ek konum parametreleri ekleyenler.
Aksine, ortam değişkenleri birden fazla programı etkilemek içindir. Bunlar ortam değişkenleridir, çünkü programın dışında ayarlanmıştır (daha fazlası aşağıdadır). Gibi belirli ortam değişkenleri HOME
veya PATH
belirli bir biçim, belirli bir anlamı var ve onlar her program için aynı anlama edeceğiz. HOME
değişken , betiğin kök ayrıcalıklarıyla çalışıp çalışmadığını kontrol etmek ve buna göre belirli eylemlere dallanmak için ortam değişkeni gibi harici bir yardımcı programla aynı anlama gelecektir . Ortam değişkenleri kalıtsaldır - alt süreçler üst ortamın kopyasını alır. Ayrıca bkz. İşlemler ebeveyn ortamını devralıyorsa, neden dışa aktarmaya ihtiyacımız var?/usr/bin/find
veya kabuğunuzla (ve dolayısıyla bir komut dosyasıyla) - işlemin altında çalıştığı kullanıcı adının ana dizini. Çevresel değişkenlerin belirli komut davranışlarını açıklamak için kullanılabileceğine dikkat edin, örneğinUID
Kısacası, ana ayrım, ortam değişkenlerinin komutun dışında ayarlanması ve değiştirilmemesi (genellikle) amaçlanırken, konumsal parametreler, komut tarafından işlenmesi gereken şeylerdir ve değişirler.
Sadece kabuk kavramları değil
Yorumlardan fark ettiğim şey, terminal ve kabuğu karıştırdığınız ve gerçekten bir zamanlar fiziksel cihazlar olan gerçek terminalleri okumanızı tavsiye etmesidir. Günümüzde, tipik olarak bahsettiğimiz "terminal", siyah arka planlı ve yeşil metinli pencere aslında yazılım, bir işlemdir. Terminal bir kabuk çalıştıran bir programdır, kabuk ise bir programdır ancak yürütmek için yazdığınız şeyi okuyan programdır (yani, etkileşimli kabuk ise; etkileşimli olmayan kabuklar komut dosyaları ve sh -c 'echo foo'
çağrı türleridir). Burada mermiler hakkında daha fazla bilgi .
Bu önemli bir ayrımdır, ancak terminalin bir program olduğunu ve bu nedenle aynı çevre kurallarına ve konum parametrelerine uyduğunu bilmek de önemlidir. Başladığınız gnome-terminal
zaman, SHELL
ortam değişkeninize bakar ve başka bir komut belirtmediğiniz sürece sizin için uygun varsayılan kabuğu oluşturur -e
. Diyelim ki varsayılan kabuğumu değiştirdim ksh
- ksh
bunun yerine gnome-terminal ortaya çıkacak bash
. Bu aynı zamanda ortamın programlar tarafından nasıl kullanıldığının bir örneğidir. Ben açıkça söylersem gnome-terminal
ile -e
belirli bir kabuk çalıştırmak için - bunu yapmak, ancak kalıcı olmayacaktır. Aksine, çevre çoğunlukla değiştirilmemelidir (bundan sonra daha fazla).
Gördüğünüz gibi, çevre ve konumsal değişkenler yalnızca kabuk değil, bir işlem / komutun da özellikleridir. Kabuk betikleri söz konusu olduğunda, C programlama dili tarafından belirlenen modeli de takip ederler. Örneğin, main
tipik olarak aşağıdaki gibi görünen C işlevini ele alalım.
int main(int argc, char **argv)
, burada argc
komut satırı argümanlarının sayısı ve argv
etkili bir şekilde komut satırı parametreleri dizisidir ve daha sonra kullanıcının ana dizin yolu, yürütülebilir dosyaları arayabileceğimiz dizinlerin listesi gibi şeylere erişmek için environ
işlev (Linux'ta man -e 7 environ
) vardır PATH
. Kabuk betikleri de benzer şekilde modellenir. Kabuk terminoloji, biz konumsal parametrelere sahip $1
, $2
süre, vb ve $#
konumsal parametrelerin sayısıdır. Ne olmuş $0
? Bu yine C programlama dilinden de modellenmiş olan argv[0]
yürütülebilir dosyanın adıdır - C "çalıştırılabilirinizin" adı olacaktır. Bu, çoğu programlama ve komut dosyası dili için oldukça doğrudur .
Etkileşimli ve etkileşimli olmayan kabuklar
Zaten ima ettiğim şeylerden biri, etkileşimli ve etkileşimli olmayan mermiler arasındaki ayrım . Komutları yazdığınız istem - bu etkileşimli, kullanıcıyla etkileşime girer. Buna karşılık bir kabuk betiğiniz olduğunda veya çalıştırdığınızda bash -c''
bu etkileşimli değildir.
Ve bu, ayrımın önemli hale geldiği yerdir. Çalıştırdığınız kabuk, konumsal parametrelerle ortaya çıkan bir işlemdir ( bash
giriş kabuğu için bir "... sıfır bağımsız değişkeninin ilk karakteri bir - veya biri --login seçeneğiyle başlatılmıştır." ( Başvuru ) )
Aksine, -c
seçenekle başlatılan komut dosyaları ve kabuklar $1
ve $2
argümanlardan yararlanabilir . Örneğin,
$ bash -c 'echo $1; stat $2' sh 'Hello World' /etc/passwd
Hello World
File: '/etc/passwd'
Size: 2913 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 6035604 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2017-08-12 14:48:37.125879962 -0600
Modify: 2017-08-12 14:48:37.125879962 -0600
Change: 2017-08-12 14:48:37.137879811 -0600
Birth: -
Ben de sh
orada kullandığım dikkat edin , çünkü -c
seçenek küçük tuhaf ilk konumsal parametre almak ve atamak $0
, genellikle programın bir adından farklı olarak.
Dikkat edilmesi gereken bir diğer şey ise konumsal parametrelerin "çerçeveli" dediğim şey olduğudur. İlk önce bash
kendi konum parametreleriyle başlattığımıza dikkat edin , ancak bu konum parametreleri echo
ve parametrelerine dönüştü stat
. Ve her program kendi yolunda anlıyor. Eğer stat
bir dizgeye verdiysek Hello World
ve dosya yoksa Hello World
bir hata oluşturur; bash
basit bir dize gibi davranır, ancak stat
bu dizenin mevcut bir dosya adı olmasını bekler. Aksine, tüm programlar ortam değişkeninin HOME
bir dizin olduğu konusunda hemfikirdir (programcı bunu mantıksız bir şekilde kodlamadığı sürece).
Çevre değişkenleri ve konumsal parametrelerle uğraşabilir miyiz?
Teknik olarak, hem etrafında karışıklık can, ama biz olmamalı sık sık konumsal parametreler sağlamak zorunda ise, çevre değişkenleri ile etrafında karışıklık. Komutları kabuk içinde bir değişken ekleyerek çalıştırabiliriz, örneğin:
$ hello=world bash -c 'echo $hello'
world
Değişkenleri yalnızca export variable=value
kabuktan veya komut dosyasından kullanarak ortama yerleştirebiliriz . Veya tamamen boş bir ortam ile bir komut çalıştırabiliriz env -c command arg1 arg2
. Ancak, özellikle büyük harfli değişkenler kullanarak veya zaten var olan ortam değişkenlerinin üzerine yazarak ortamla uğraşmanız önerilmez. Standart olmasa da tavsiye edilir.
Konumsal parametreler için, bunları ayarlamanın yolu açıktır, sadece komuta ekleyin, ancak bunları diğer akıllıca ayarlamanın yanı sıra shift
komut aracılığıyla bu parametrelerin listesini değiştirme yolları da vardır .
Sonuç olarak, bu ikisinin amacı farklıdır ve bir nedenle var olurlar. Umarım insanlar bu cevaptan biraz içgörü kazanırlar ve bu yanıtı yazmak benim için olduğu gibi okumak çok eğlenceliydi.
Set komutu hakkında not
set
Komut, bu gibi manuel davranacaktır göre (Bash manuel, vurgu eklenmiştir):
Seçenekler olmadan, her kabuk değişkeninin adı ve değeri, o anda ayarlanan değişkenleri ayarlamak veya sıfırlamak için giriş olarak yeniden kullanılabilecek bir biçimde görüntülenir.
Diğer bir deyişle set
, mesela bazıları çevrede olan kabuğa özgü değişkenlere bakar HOME
. Buna karşılık komutlar , bir komutun çalıştığı gerçek ortam değişkenini beğenir env
ve printenv
bakar. Ayrıca bkz bu .
export 3
açmak için$3
çevre değişkene. Yapamazsınızunset 3
; ve tuşlarını$3
kullanarak yeni bir değer atayamazsınız3=val
.