Category Archives: UNIX

Shell – Script Çalıştırma – Ortam Değişkenlerini Set Etmek


lifeinbeta@lifeinbeta:~/CSWORKS/C/soexample$ set LD_LIBRARY_PATH = /opt/lib:$LD_LIBRARY_PATH
lifeinbeta@lifeinbeta:~/CSWORKS/C/soexample$ echo $LD_LIBRARY_PATH

yaptım, ama olmadı, çünkü;

Shells and Shell Scripts yazısında açıklandığı üzere:

Running Scripts kısmında;

Bir Shell Script’ini çalıştırmak için üç farklı yol vardır:

Direct Execution: Bir Shell Script‘ini çalıştırabilmek için en basit yol, chmod ile text file‘ı executable yapmaktır. Bundan sonra, script, eğer current working directory‘de ise ya da shell‘in PATH‘inde tanımlı ise, adı yazılarak çalıştırılabilir.

Bir script çalıştırıldığında, yeni bir shell yaratır ve bu yeni shell‘de script içinde belirtilmiş olan her bir komutu sırayla çalıştırır. Script‘in sonuna gelindiğinde, yeni shell kapanır. Yeni shell’in script dolayısıyla sistemde yaptığı değişiklikler, shell sonlandığında kaybolur.

Shell Execution: Bir script’i yeni shell context’i içinde çalıştırmanın diğer yolu, shell’i script’i parametre olarak verip çalıştırmaktır. Bu aslında Direct Execution‘dur. Doğrudan, sh‘ı çalıştırarak, sh options değiştirilebilir.

csh -x change şeklinde çalştırıldığında, çalışan komutlar da output‘ta gösterilir.

source Execution: Bir script‘i mevcut shell’de çalıştırabilmek için, internal shell command olan source kullanılır. Çalıştırma, mevcut shell’in context‘inde olduğu için, script‘in shell’de yaptığı değişiklikler, shell sonlanıncaya kadar durur.

Burada, her shell‘in bir child process olduğu ve scope’u olduğu anlatılıyor. Benim karşılaştığım problem ise, aslında, tam olarak bununla ilgili değil ama, sistem geneli ortam değişkenleri scope‘u, environment scope – yani kısaca Environment ile ilgili.

Yukarıda yaptığım shell işlemlerinde, öncelikle bir terminal açmıştım. Terminal, bir shell başlattı. Bu yeni shell‘de yazmış olduğum, set komutu bir ortam değişkenini değiştirdi. Yeni bir terminal, yani shell açıp bu ortam değişkenini yazdırdığımda değerinin değişmediğini gördüm.

Export

A – Bourne Shell mark for export flag‘de belirtildiği gibi:

Bir değişkeni ortam – environment‘da bulundurabilmek için, o değişkeni explictly export etmek gerekir ki diğer programlar da onu bulabilsin.

Burada ayrıca,

Bunu yapmanın bir diğer yolu, set‘i -a option‘u ile birlikte kullanmaktır:
set -a
Bu yapıldığında, değiştirilen ya da yaratılan değişken export edilir.

Bu işlemlerin ve export‘un sebebi, UNIX – MAN Sayfaları ile Dosya Okuma-Arama Komutları ve Ortam Değişkenleri yazısında yazıyor.

Ayrıca, Environment Variables‘a bakılabilir.

Yukarıdaki anlatılanlardan anlaşılacağı gibi:

lifeinbeta@lifeinbeta:~/CSWORKS/C/soexample$ set LD_LIBRARY_PATH = /opt/lib:$LD_LIBRARY_PATH
lifeinbeta@lifeinbeta:~$export LD_LIBRARY_PATH
lifeinbeta@lifeinbeta:~/CSWORKS/C/soexample$ echo $LD_LIBRARY_PATH

yazmalıydım.

Yukarıdaki, shell‘de script çalıştırma yöntemlerinden ilkini kullandım. export ile ortam değişkenini değiştirdim. Ancak, açık olan shell, yani child process sonlanana kadar geçerli olacaktır. Bu yüzden her defasında bunu set etmek yerine,

Uygun login dosyası – GNU Bash Shell için .bash_profile kullanılarak her oturum için LD_LIBRARY_PATH otomatik olarak set edilebilir.

.bashrc‘de şunu yazdım:

export LD_LIBRARY_PATH=/opt/lib:$LD_LIBRARY_PATH

Bunun için;

lifeinbeta@lifeinbeta:~/CSWORKS/C/soexample$ vim ~/.bashrc
lifeinbeta@lifeinbeta:~/CSWORKS/C/soexample$ source ~/.bashrc
lifeinbeta@lifeinbeta:~/CSWORKS/C/soexample$ printenv LD_LIBRARY_PATH
/opt/lib:

işlemlerini yaptım. En son,

.bashrc‘de şunlar yazılıydı:

lifeinbeta@lifeinbeta:~$ cat .bashrc
export JAVA_HOME=/usr/lib/jvm/java-6-openjdk
export PATH=$PATH:$JAVA_HOME/bin:~/play-1.1.1
export LD_LIBRARY_PATH=/opt/lib:$LD_LIBRARY_PATH
Advertisements

Leave a comment

Filed under Shell, UNIX

UNIX – i-node, Hard Link ve Soft Link


Making symlinks to replace GLUT yazısını okurken;

ln -s /usr/lib/libfreeglut.so.0.2.0 /usr/lib/libglut.so.3
ln -s /usr/lib/libfreeglut.so.0.2.0 /usr/lib/libglut.so.3.7
ln -s /usr/lib/libfreeglut.so.0.2.0 /usr/lib/libglut.so.3.7.0

ile karşılaştım ve neden link yapılmaya gerek duyulduğunu merak ettim.

Değişik versionlardaki .so ları(.so,.so.3,.so.3.9) tek bir versiyona(.so.0.2.0) link ettik. Ayrıca, kütüphane ismini(libglut) de daha belirgin bir hale(libfreeglut) getirdik. Artık, libglut kütüphanelerinden herhangi biri yerine sadece libfreeglut.0.2.0‘ı kullanabiliriz. Sanırım, bu şekilde olası karmaşaları önledik.

i-node

UNIX’te her dosya, dosya içeriğiyle ilgili önemli bilgiler tutan, i-node denilen, bir veri yapısıyla ilişkilendirilir. i-node; dosyanın boyutu, son erişim zamanı, son değiştirme zamanı, kendisinin en son değiştirilme zamanı, dosyanın sahibi, izin bilgileri, dosyanın disk üzerinde bulunan verisine olan pointer‘ları ve dosyaya verilen link sayısını tutar. UNIX’te dizinlere karşılık gelen veri yapısı, dizindeki dosya isimlerini tutar. Bir dosya ismi, ilişkili olduğu i-node‘a pointer dır.

Dosya ismi, veri yapısına bir pointer ise bu veri yapısına erişmek için başka pointer‘lar da kullanabiliriz. Bunun çeşitli amaçları vardır. Dosya ismi harici böyle pointerlara link denir. Hard Link ve Soft Link vardır.

Hard Link, bir dosyanın i-node‘una pointer‘ olan başka bir dosyadır. Elimizde file1 olsun. İçeriği bravo, milord! 🙂 olsun. Bu dosyaya file2 isimli bir dosyayı link edelim.
ln file1 file2
Sağdan sola okunursa, file2,file1‘e link edilmiştir. Şimdi cat file2 dersek, file2‘nin de bravo milord! dediğini görürüz. Yani, bu iki dosya ismi de aynı i-node‘a pointer oldu.

Soft/Symbolic Link, oluşturulduğunda, file2 olsun ve file1‘e link edilmiş olsun, file2‘nin içerisinde file1 yazılır. Bu şekilde file1‘in içeriğine file2 ile erişebiliriz. ln -s file1 file2 şeklinde yazılır.

lifeinbeta@lifeinbeta:~/Desktop$ touch file1
lifeinbeta@lifeinbeta:~/Desktop$ vim file1
lifeinbeta@lifeinbeta:~/Desktop$ cat file1
bravo milord!
lifeinbeta@lifeinbeta:~/Desktop$ ln -s file1 file2
lifeinbeta@lifeinbeta:~/Desktop$ ls -F
...
file1                                 ...
file2@                                ...
lifeinbeta@lifeinbeta:~/Desktop$ cat file2
bravo milord!

Görüldüğü gibi, sembolik link @ işareti ile belirtiliyor. Hard Link‘te olduğu gibi, link edilmiş olan dosyanın içeriğini değiştirdiğimizde gerçek dosyanın içeriği de değiştirilmiş olur.

UNIX’te bir dosya sistemi hiyerarşisi, birden fazla disk ya da disk bölümü üzerindeki dosya sistemlerinden oluşabilir. Her dosya sistemi, kendisinden sorumludur, diğer dosya sistemleri hakkında bilgiye sahip değildir.

Hard Link‘ler, bir dosya sisteminin kendi veri yapısı olan bir i-node ile ilişkili olduğu için, sadece kendi dosya sistemi hakkında bilgiye sahiptir. Bu nedenle, bir dosya sistemindeki bir dosyadan, başka bir dosya sistemindeki bir dosya için oluşturulamaz.

Soft linkler ise dosya ismini içerdiği için bu durumdan etkilenmez. freeglut için aynı dosya sistemi içinde çalışacağımdan aslında Hard Link de oluşturabilirdim.

1 Comment

Filed under UNIX

UNIX – MAN Sayfaları ile Dosya Okuma-Arama Komutları ve Ortam Değişkenleri


Ubuntu Software Center‘la ya da apt-get install ile Software Repo‘larından yüklediğim programların yüklendiği yerleri bulma konusunda hep sıkıntı yaşadım.

Aslında, Ubuntu‘da kullanıcının yüklediği dosyaların, File System üzerinde nereye yüklendiğini bir türlü bir yere not etmedim. Hala da emin değilim, yani hepsini adam akıllı bilmiyorum. Ama bu yazıya onları da ekleyeceğim.

Yüklediğim uygulamaların yerlerini bulmak için çeşitli command-line utility‘lerini üstün körü kullandım.(find, locate gibi) Ancak, gerek parametrelerini gerekse parametre yapılarını tam anlamıyla kullanamadım. Her defasında da Linux Commands diye aratmaktan sıkıldım. Çünkü, arama sonuçlarında üst sıralarda çıkan kaynakların büyük çoğunluğu, zaten bilinen genel komutlardan bahsediyor.

Sonunda aradığım komutun dpkg olduğunu buldum.

dpkg -S freeglut3

ile aratarak freeglut paketinin dosyalarının yerlerini bulabildim.

UNIX Programcılarının meşhur sözü:

Read the frickin’ man page!” hep aklımın bir köşesindeydi, ancak zahmet edip okumak istemedim(zaten belirtilen cümlede de biraz zahmet etmek gerektiği vurgulanıyor).

Neyse, bu kadar giriş(prologue) yeter. 🙂

MAN sistemini detaylı bir şekilde inceleyelim.

MAN Sistemi Neden Var?

Konuya, Speaking UNIX: Man oh Man yazısını açarak başlayalım.

UNIX Komut Satırı’nda yazılabilecek 1500’den fazla komut vardır. Bu komutların birçok parametresi(option) vardır. Ayrıca, yeni eklenen programların çalıştırılabilir dosyaları da hesaba katıldığında, bu komutların her birini, her bir parametresini, belli bir işi yapmak için gerekli parametre kombinasyonunu hatırlamak çok zordur.

İşin kötüsü, UNIX komutları 40 yılı aşkın süredir var ve komut yapısını belli kategorilere ayırmak zor. Mesela, dosya sistemi üzerinde işlem yapma komutu olan ls nin -l parametresi long list(uzun liste) anlamında iken diğer dosya sistemi komutlarında aynı anlama gelmez. Ayrıca bu parametre hiç olmayabilir de. Komutlar buna çözüm olarak --help parametresi ile komutun bir özetini sağlarlar ama çoğu zaman bu özet bilgi, yapılmak istenen işi yapmakta yeterli olmaz.

Daha önceden bir işi yapmak için kullanılan komutun yapısını hatırlama problemini aşmak için birkaç yol, çok kullanılan komutlara parametreleri ile beraber bir alias vermek ya da belli komutları bir shell script‘inde toplamak olabilirdi. Ancak, bu da çoğu zaman yeterli olmaz ki öncelikle daha alias oluşturmadan o komutu yazabilmek gerekir.

Tüm bu problemlerden dolayı, UNIX online referans sistemi yapılmıştır.

Man Sistemi Nasıldır?

UNIX Man Sistemi, iki kısımdan oluşur. Birincisi, online referans sistemi ikincisi de bu sistemdeki referans sayfalarını okuyabilen bir okuyucudur. Sayfalara man page denir. Okuyucu program ise man komutuyla çağrılan yazılım parçasıdır.

man cd

man dpkg

man man

ile herhangi bir programın man sayfası okunabilir.

Yüklü her UNIX programı(daha doğrusu yazılım parçası, program harici UNIX yazılım bileşenlerinin de man sayfaları vardır), kendi man sayfasını da bulundurur.

Programların man sayfalarının bulunup okunacağı yerler(repo)

/usr/man

/usr/share/man

ya da bazen programın kurulum dizininin, mesela MySQL’de,

/usr/local/mysql/man

altında oluşturulan dosyalarda belirtilir.

lifeinbeta@lifeinbeta:/usr/share/man$ cd tr
lifeinbeta@lifeinbeta:/usr/share/man/tr$ ls
man1 man5 man8
lifeinbeta@lifeinbeta:/usr/share/man/tr$ cd man1
lifeinbeta@lifeinbeta:/usr/share/man/tr/man1$ ls
chage.1.gz chfn.1.gz login.1.gz passwd.1.gz su.1.gz
lifeinbeta@lifeinbeta:/usr/share/man/tr/man1$ cd ..
lifeinbeta@lifeinbeta:/usr/share/man/tr$ cd man5
lifeinbeta@lifeinbeta:/usr/share/man/tr/man5$ ls
passwd.5.gz shadow.5.gz
lifeinbeta@lifeinbeta:/usr/share/man/tr/man5$ cd ..
lifeinbeta@lifeinbeta:/usr/share/man/tr$ cd man8
lifeinbeta@lifeinbeta:/usr/share/man/tr/man8$ ls
groupadd.8.gz groupmod.8.gz useradd.8.gz usermod.8.gz
groupdel.8.gz synaptic.8.gz userdel.8.gz
lifeinbeta@lifeinbeta:/usr/share/man/tr/man8$

Yukarıda görüldüğü gibi, her repo çeşitli alt kısımlara(man1, man2, … ,man8) bölünmüştür. Bunların herbiri bir komut kategorisini belirtir. Böyle bir şeye ihtiyaç duyulmasının nedeni, komutları bir namespace ile ilişkilendirmektir. UNIX’te bir sürü yazılım parçası olduğu için yeni oluşturulan bir yazılım parçasına verilecek ismin diğerlerinden birininin ismiyle çakışma ihtimali vardır. Mesela, iki farklı crontab komut vardır. 1. bölümde(man1) açıklaması bulunan crontab, Job Scheduling için kullanılılan bir programdır. 5. Bölümdeki crontab ise bir dosya formatıdır. Hangi crontab‘ın man sayfasına bakılmak istendiği aşağıdaki gibi belirtilir:

$ man 1 crontab
$ man 5 crontab

Bir MAN Sayfasının Anatomisi

Man Sayfalarının yapıları birbirine çok benzer. Bu yapı bir gelenek haline gelmiştir. Bu nedenle, man sayfalarını okumaya alıştıktan sonra okumak zevkli(!) hale gelebilmektedir.

Bir man sayfası en az, şu beş bölümden oluşur; name(isim), synopsis(özet), description(açıklama), examples(birkaç örnek), see also(bu komutla ilişkili diğer komutlara referanslar). Şimdi bunları açıklayalım:

  • name: yazılım parçasının(program, fonksiyon ya da dosya formatı) adı ve ne işe yaradığını belirten tek satırlık açıklama
  • synopsis: yazılımın nasıl kullanılabileceği konusunda bir özet sağlar. Eğer man sayfası bir çalıştırılabilir dosyanın ise, onun mandatory(zorunlu) ve optional(zorunlu değil) parametrelerini(option ya da switch), parametre formatı ve parametre sırasını belirtir. Eğer sayfa bir sistem çağrısı ya da bir kütüphane fonksiyonun ise, fonksiyonun parametrelerini ve header dosyası gerekiyorsa o fonksiyonun hangi header‘ı kullandığını belirtir.
  • description: Bu kısımda, komutun işlevinin açıklaması vardır. [OPTIONS] kısmında belirtilen parametrelerin ne iş yaptıkları açıklanır.

du komutunun;

BSD UNIX‘teki synopsis‘i,
du [-H | -L | -P] [-a | -s | -d depth] [-c] [-h | -k | -m | -g] [-x]
[-I mask] [file ...]
şeklindedir.
Burada, du komutundan sonra istenirse(optionally) -H, -L, -P parametrelerinden herhangi biri girilebilir.
Daha sonra -a, -s, -d parametrelerinden herhangi biri girilebilir.
Eğer -d parametresi girilmişse argüman belirtilmelidir.
Daha sonra -c parametresi girilebilir.
Bundan sonra -h, -k, -m ya da -g den biri girilebilir ya da hiçbiri girilmeyebilir.
Sonraki parametrelerden biri girilecekse devam edilir.
-x parametresi girilebilir ya da girilmeyebilir.
Daha sonra -I parametresi girilirse yanına argümanı belirtilmelidir.
Daha sonra dosya ad(lar)ı belirtilir.
Buradaki “...” birden fazla dosya girilebileceğini gösterir.
Burada parametre sırası önemli değildir.
Bu komut doğrudan du file1 gibi girilebilir.

Özetle, parametre grupları checkbox gibi düşünülür. Parametre grubundaki parametreler ise radio butonları gibidir.

Ubuntu’da synopsis, BSD UNIX’te gösterildiği gibi gösterilmez:

DU(1) User Commands DU(1)

NAME
du - estimate file space usage

SYNOPSIS
du [OPTION]... [FILE]...
du [OPTION]... --files0-from=F
DESCRIPTION
Summarize disk usage of each FILE, recursively for directories.

Mandatory arguments to long options are mandatory for short options
too.

-a, --all
write counts for all files, not just directories
şeklinde gösterilir. Synopsis‘te komut yapısın  [OPTIONS] ile belirtilir. Bu kısımda belirtilen parametreler, DESCRIPTION kısmındaki açıklamadan sonra açıklanır.

GNU UNIX Komutlarının Parametre Yapısı

UNIX komutlarında parametreler case-sensitive‘dir. Yukarıda görüldüğü gibi hem ayrı işleri yapan -H hem de -h parametresi vardır.
UNIX’te parametreler tek harfliyse komutta du -a -H şeklinde ayrı ayrı belirtilebileceği gibi, -Ha şeklinde birleştirilebilir.
Parametre bir kelime ise(Yukarıdaki man sayfasında -a, --all şeklinde belirtildiği gibi) parametrenin başına “--” konur.
Birden fazla kelimeden oluşuyorsa, --apparent-size da olduğu gibi, kelimeler arasına “-” konur.
NOT: Bazı programlar(find -name 'core' gibi) bu yapıya uymayabilir.
Daha detaylı açıklama için buraya bakılabilir.

Parametre yapısı konusunda şurada bazı genel UNIX parametrelerinin anlamları var. Bu özetin daha genel hali ise Art of UNIX Programming – Eric Raymond kitabının bir bölümünün anlatıldığı yer olan burada.

Environment

Man Sayfalarında mutlaka olan bu beş kısım haricinde en çok Environment kısmı bulunur.
lifeinbeta@lifeinbeta:~$ man man
...
ENVIRONMENT
MANPATH
If $MANPATH is set, its value is used as the path to search for
manual pages.

MANROFFOPT
The contents of $MANROFFOPT are added to the command line every
time man invokes the formatter (nroff, troff, or groff).

MANROFFSEQ
If $MANROFFSEQ is set, its value is used to determine the set of
preprocessors to pass each manual page through. The default
preprocessor list is system dependent.

MANSECT
If $MANSECT is set, its value is a colon-delimited list of sec‐
tions and it is used to determine which manual sections to
search and in what order.

Bu kısımda bu komuta ait Environment Variables(Ortam Değişkenleri) belirtilir.

Ortam Değişkenleri

UNIX Komutları olan; envset ve printenv ile bütün ortam değişkenleri ve değerleri görülebilir. Burada env ve set ortam değişkenlerine değer atamak için de kullanılabilir. printenv ‘e argüman olarak bir ortam değişkeni verildiğinde onun değeri görülebilir. Bir shell açık iken herhangi bir ortam değişkenine değer atandığında o değerin bütün sistemde geçerli olabilmesi için (ortam değişkenleri, çalışan bir shell process‘ine göredir, yani global değil yereldir. Mesela, bir terminal açıkken bir shell process‘i oluşturulur. Başka bir terminal açıldığında farklı bir shell process‘i oluşturulur. Bu yüzden bir shell’de değiştirdiğimiz ortam değişkeninin değeri, diğerinde geçerli olmaz.)

Daha teknik olarak ifade etmek gerekirse,

UNIX, parent process tarafından oluşturulmuş bütün process‘lere bilgi aktarmak için Ortam Değişkenlerini kullanan bir mekanizmaya sahiptir. Sisteme giriş yapıldığında, önceden tanımlı belli sayıda değişken(varsayılan ortam değişkenleri: PATH, HOME vs.) otomatik olarak sağlanır. Bu listeye yeni bir Ortam Değişkenini ve değerini eklemek için shell start up dosyaları kullanılabilir.

lifeinbeta@lifeinbeta:~$ cat .bashrc
...
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000
...
# TAHA YAVUZ BODUR WROTE:
export JAVA_HOME=/usr/lib/jvm/java-6-openjdk
export PATH=$PATH:$JAVA_HOME/bin:~/play-1.1.1

Çalışan her child process ortam değişkenlerini ve değerlerini inherit  eder. Parent Processten child process’lere bilgi akışı tek yönlüdür. Bunun sebebi, her child process‘in kendi kafasına göre Ortam Değişkenlerini değiştirmesini engellemektir. Böyle bir durumda kimin neyi değiştirdiği bilinemezdi. Bu nedenle, bir child process bir ortam değişkenini değiştirmek istediğinde, ortam değişkeninin değerini değiştirdikten sonra aşağıdaki gibi,

export VARIABLE=value  # Bourne, bash, ve bunlar gibi shell'ler için.

bu değişikliği sisteme bildirir. Artık, bütün child process‘ler bu yeni değerleri kullanabilir.

Bununla birlikte, eğer yukarıdaki komut doğrudan açık terminal’den girilirse, çalışan bu terminal açıldığında oluşturulmuş olan shell process‘i üzerinden işletileceği için, yine bu shell‘de daha sonra çalıştırılacak olan yeni komutlar ortam değişkenin yeni değerini görebilir. Ancak, bu komut ayrı bir shell script‘i olan .bashrc içine yazıldığında, değiştirilen değeri güncelleyebilmek için bu script‘in çalıştırılması gerekir. Bu yüzden, UNIX Command Execution kısmında belirtildiği gibi, source .bashrc komutu çalıştırılmalıdır.

NOT: Shell bir interpreter‘dır(yorumlayıcı). Bu program, yeni bir komut girildiğinde, o komutun çalıştırılabilir dosyasını PATH‘de belirtilen dizinlerde arar. /usr/bin dizininde(built-in shell komutlarının bulunduğu dizin) bulur. Bulduğunda, shell process‘i(parent process) tarafından fork edilir. Yani, bir child process oluşturulur.

Ayrıca, yukarıda belirttiğim komutların çıktıları aşağıdaki gibidir:

lifeinbeta@lifeinbeta:~$ env
ORBIT_SOCKETDIR=/tmp/orbit-lifeinbeta
SSH_AGENT_PID=1368
TERM=xterm
SHELL=/bin/bash
...
DESKTOP_SESSION=gnome
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/lib/jvm/java-6-openjdk/bin:/home/lifeinbeta/play-1.1.1
PWD=/home/lifeinbeta
JAVA_HOME=/usr/lib/jvm/java-6-openjdk
GDM_KEYBOARD_LAYOUT=tr
...
HOME=/home/lifeinbeta
...

Man sayfalarında navigasyon

man komutunun man sayfası çok uzundur(706 satır). Bu yüzden bütün açıklamayı okumak zordur. Bunun için man sayfalarını etkili bir şekilde kullanabilmek gerekir.

UNIX’te bir dosyanın içeriğini standard output‘ta(stdout, standard input -> stdin) göstermek için; cat,more,less,head ve tail kullanılabilir.

cat

cat, parametre olarak belirtilen dosya ya da dosyaların tüm içeriklerini arka arkaya standart output‘a yazar.
lifeinbeta@lifeinbeta:~/CSWORKS/C$ cat dummy1.c dummy2.c
#include <stdio.h>

int main() {
printf("Hello cruel world\n","%s");
return 0;
}
#include <stdio.h>

int main() {
printf("Shared library'nin ikinci .o bilesenini oluşturacak.");
return 0;
}

Ayrıca, cat’ta redirection işlemleri yapılabilir.

lifeinbeta@lifeinbeta:~/CSWORKS/C$ cat dummy1.c dummy2.c >> dummy_rm.c
lifeinbeta@lifeinbeta:~/CSWORKS/C$ cat dummy_rm.c
#include <stdio.h>

int main() {
printf("Hello cruel world\n","%s");
return 0;
}
#include <stdio.h>

int main() {
printf("Shared library'nin ikinci .o bilesenini oluşturacak.");
return 0;
}
Burada, dummy1.c ve dummy2.c nin stdout‘a yazılan verileri redirection operatörü(>>) ile dummy_rm.c’nin stdin‘ine aktarılır, stdin‘deki bu veriler dummy_rm.c‘ye yazılır.
cat, belirtilen bütün dosyalardaki tüm içeriği, en son dosyanın EOF‘ı ile karşılaşıncaya kadar stdout‘a yazar. Bu nedenle uzun içerikli dosyalarda kullanışlı değildir.
Uzun sayfalarda hareket ederken more ve less gibi sayfalama komutları kullanılabilir.

More ve Less Sayfalama Komutları

more, dosya içeriğini, cat gibi, stdout‘a bir defada alır ve belli uzunlukta bölümler halinde terminalde gösterir.
lifeinbeta@lifeinbeta:~/CSWORKS/helloworld/public/javascripts$ more jquery-1.4.2.min.js
/*!
* jQuery JavaScript Library v1.4.2
* http://jquery.com/
...
--More--(1%)
şeklinde, toplam sayfa boyutunun ne kadarın gösterildiği(1%) yazar.

less, more ve cat‘e göre hızlıdır. Çünkü, dosyadaki tüm veriyi birden stdout‘a almaz. O anda açık olan terminale sığdırabildiği kadar veriyi stdout‘a yazar. Aşağıdaki hareket tuşlarından herhangi birine bastıkça tuşun ilerleme miktarı kadar veriyi stdout‘a yazar.

Navigasyon Tuşları

Bölümler arasında hareket ederken,

ENTER, bir satır alta geçer.
SPACE, bir sonraki bölüme geçer.
CTRL-), 8 Karakter sağa gider.
CTRL-(, 8 Karakter sağa gider.
CTRL-B, bir önceki bölüme döner.
y, bir satır geri gelir.
b, bir terminal boyu kadar geri gelir.
[:10g], 10 satır geri gelir. (ex, vi, vim‘deki komut yapısı gibi.)
[/synopsis], “synopsis” kelimesini bulur ve oraya odaklanır.

NOT: “/” ile ileriye doğru arama yapılır. “?” ile geriye doğru arama yapılır. Arda arda arama(incremental search) imkanı sağlamaz.

[:e diger_dosya], görüntülenen dosyadan çıkıp diğer dosyayı görüntüler.
q ya da CTRL^Z, less‘ten çıkar.

Özetle, uzun man sayfaları için less çok kullanışlıdır.

Örn:
man man | less

NOT: buradaki “|”(pipe) ile, man komutunun stdout‘a yazdığı man sayfası, more komutunun stdin‘ine yazılır. Bu sayede, less komutu bu veriyi gösterir.

head ve tail

Bu komutlar, sırasıyla baştan ya da sondan, argüman olarak belirtilen dosyalardan, -n argümanı ile belirtilen(n, okunmak istenen satır sayısını gösterir, varsayılan olarak 10’dur.) belirtilen sayı kadar satırı stdout‘a yazar.
tail ile ayrıca, eğer hali biz baktığımız sırada yazılan bir dosya varsa, dosyaya yazılanları takip etmek için -f  parametresi(follow) ile kullanılabilir.
tail -f /program/log/dosyası

Man sistemini daha iyi kullanmak için

  1. man komutunun Environment Variable‘larından biri olan MANPATH, tıpkı shell‘in bir Environment Variable‘ı olan PATH gibi, bir dizin listesi tutar. PATH‘in tuttuğu dizin listesi, shell‘den çağrılabilecek çalıştırılabilir dosyalarının yerlerini içerir. MANPATH de man sayflarının bulunabileceği dizinleri belirtir. Man sayfalarının konumlarının genelde belli bir yer olduğunu ama bazı programların man dosyalarını kendi dizinleri içinde tutabileceğini söylemiştim.
  2. Man sayfası, aradığımız yazılım parçasının tam adını bilmiyorsak, man repo‘larından man -k aranacak_seyin_kalibi ile aratılabilir.
  3. Varsayılan yerinde olmayan, programın kurulum dizininde olan bir man sayfasını okurken man ./manfile ile okumalıyız. Yani, ./ ile bulunduğumuz dizindeki manfile diye özellikle belirtmeliyiz. Eğer man manfile yazarsak, bütün MANPATH‘i tarar. Eğer belirttiğimiz dizin MANPATH‘e eklenmemişse de bu man dosyasını bulamaz.
  4. MANPATH’in mevcut değerine,
lifeinbeta@lifeinbeta:~/CSWORKS/C$ echo $MANPATH

lifeinbeta@lifeinbeta:~/CSWORKS/C$ manpath
/usr/local/man:/usr/local/share/man:/usr/share/man:/usr/lib/jvm/java-6-openjdk/man
ile bakılabilir.

Şimdi, gelelim asıl mevzuya:

Man sayfalarını bu kadar detaylı öğrenmek elde edeceğim kazanca değecek mi diye düşündüm. Tam emin değilim 🙂 Ancak, benim için asıl önemli olan UNIX üzerinde aradığım şeyi kolayca bulabilmekti. Bu yüzden;

UNIX’te Aranan Bir Şeyi Bulabilmek

Öncelikle which ve find kullanılır.
Ayrıca, Debian Package Manager bulunan Linux sistemlerinde dpkg kullanılabilir.
Şimdi artık bu çalıştırılıabilir dosyaların man sayfalarını inceleyebiliriz:

which – Çalıştırılabilir Dosyları Bulmak

Bulmak istediğimiz çalıştırılabilir dosya(lar)ın ad(lar)ını biliyorsak,
lifeinbeta@lifeinbeta:~$ which java exaile chromium-browser
/usr/bin/java
/usr/bin/exaile
/usr/bin/chromium-browser
yazılır. Bu komutta dosyanın mutlaka tam adı belirtilmelidir.

find

Bu komut ile wildcards ve regular expressions kullanarak, belirttiğimiz dosyanın dosya sistemindeki root‘undan başlayarak tüm sistemde arama yapabiliriz.

Man Sayfası:

FIND(1) FIND(1)

NAME
find - search for files in a directory hierarchy

SYNOPSIS
find [-H] [-L] [-P] [-D debugopts] [-Olevel] [path...] [expression]

DESCRIPTION
This manual page documents the GNU version of find. ...
...
EXPRESSIONS
The expression is made up of options ..

OPTIONS
All options always return true.

TESTS
...
-executable
Matches files which are executable and directories which are searchable

-name pattern
Base of file name 
(the path with the leading directories removed) 
matches shell pattern pattern. 
The metacharacters (`*', `?', and `[]') match a `.' 
at the start of the base name 
(this is a change in findu‐
tils-4.2.2; see section STANDARDS CONFORMANCE below). ... 
The filename matching is performed with the use of the fnmatch(3) library function. 
Don't forget to enclose the pattern in quotes in order to protect it from expansion by the shell.

-path pattern
File name matches shell pattern pattern. The metacharacters do not treat `/' or `.' specially; so, for
example,
find . -path "./sr*sc"
will print an entry for a directory called `./src/misc' (if one exists). To ignore a whole directory tree,
use -prune rather than checking every file in the tree.

-readable
Matches files which are readable. ...

-regex pattern
File name matches regular expression pattern. This is a match on the whole path, not a search. For exam‐
ple, to match a file named `./fubar3', you can use the regular expression `.*bar.' or `.*b.*3', but not
`f.*r3'. The regular expressions understood by find are by default Emacs Regular Expressions, but this can
be changed with the -regextype option.

ACTIONS

-delete
Delete files; true if removal succeeded. ...

-exec command ;
Execute command; true if 0 status is returned.

OPERATORS

Listed in order of decreasing precedence:

( expr )
Force precedence. Since parentheses are special to the shell, you will normally need to quote them. Many
of the examples in this manual page use backslashes for this purpose: `\(...\)' instead of `(...)'.

! expr True if expr is false. This character will also usually need protection from interpretation by the shell.

-not expr
Same as ! expr, but not POSIX compliant.

expr1 expr2
Two expressions in a row are taken to be joined with an implied "and"; expr2 is not evaluated if expr1 is
false.

expr1 -a expr2
Same as expr1 expr2.

expr1 -and expr2
Same as expr1 expr2, but not POSIX compliant.
şeklinde uzayıp gider. Tüm man sayfasını buraya yazmadan bitirdiğim iyi oldu 🙂

Örnekler

Synopsis‘te belirtilen komut yapısından hareket edersek;

  1. find / stdio.h gibi bir şey yazarsak 🙂 birçok ! sonuç dönecektir. Yani, find’ın belirttiğimiz yapıyla, belirtilen dizindeki dosya isimlerini değil, bu dizin ve onun alt dizinlerindeki dosyaların içlerinde “stdio.h” karakterlerini aradığını anlarız.
  2. Sadece dosya ismine göre, dosya içerisinde arama yapmadan, arama yapmak istersek,
    lifeinbeta@lifeinbeta:~$ find / -name "stdio.h"
    ...
    find: `/tmp/.esd-114': Permission denied
    find: `/root': Permission denied
    /usr/include/bits/stdio.h
    /usr/include/c++/4.4/tr1/stdio.h
    /usr/include/stdio.h
    find: `/var/cache/ldconfig': Permission denied
    find: `/var/log/samba/cores': Permission denied
    ...
    ^Z
    [2]+  Stopped                 find / -name "stdio.h"
    lifeinbeta@lifeinbeta:~$ sudo find / -name "stdio.h"
    [sudo] password for lifeinbeta:
    /usr/include/bits/stdio.h
    /usr/include/c++/4.4/tr1/stdio.h
    /usr/include/stdio.h

    yapabiliriz. Synopsis‘te belirtilen [expression] kısmına, -name "stdio.h" yazdık. İlk durumda Permission Denied hataları verdi. Bunları önlemek için, sudo ile superuser olarak ikinci defa aynı komutu çalıştırdık.

  3. [expression] kısmındaki parametreleri yazmaya devam edebiliriz. -ls ile bulunan sonuçları tablo yapısı halinde gösterebiliriz.
    lifeinbeta@lifeinbeta:~$ sudo find / -name "stdio.h" -ls
    170601    8 -rw-r--r--   1 root     root         5654 Jan 22 01:51 /usr/include/bits/stdio.h
    780739    4 -rw-r--r--   1 root     root         1210 Mar 27  2010 /usr/include/c++/4.4/tr1/stdio.h
    197965   32 -rw-r--r--   1 root     root        31109 Jan 22 01:51 /usr/include/stdio.h

    şeklinde.

  4. Man Sayfasında OPERATORSkısmındaki açıklamadan gidersek,
    lifeinbeta@lifeinbeta:~$ sudo find / \(-name '*.o' -o -name '*.h' \) -print
    find: invalid expression; you have used a binary operator '-o' with nothing before it.
    lifeinbeta@lifeinbeta:~$ sudo find / \( -name '*.o' -o -name '*.h' \) -print
    ...
    /home/lifeinbeta/Desktop/Samples/jpgtn/src/common.h
    /home/lifeinbeta/Desktop/Samples/jpgtn/src/writejpeg.o
    /home/lifeinbeta/Desktop/Samples/jpgtn/src/jpgtn.h

    şeklinde bir işlem yapabiliriz. Burada ilk denemede hata vermesinin sebebi,         \(-name ... ifadesinde, \( den sonra bir boşluk karakteri olmamasıydı. Neyseki man sayfasına bakarak bu hatayı düzelttim.

locate

Herhangi bir dosyayı bulmak için kullanılır. Dosya adı doğrudan yazıldığında, aranan dosya adının, dosya adlarının herhangi bir yerinde geçip geçmediğine bakılır. Regular Expressions ile dosya isimleri filtrelenebilir.

Man Sayfası

locate(1)                                                            locate(1)

NAME
       locate - find files by name

SYNOPSIS
       locate [OPTION]... PATTERN...
DESCRIPTION
       locate  reads  one or more databases prepared by updatedb(8) and writes
       file names matching at least one of the PATTERNs  to  standard  output,
       one per line.

       If  --regex is not specified, PATTERNs can contain globbing characters.
       If any PATTERN contains no globbing characters, locate  behaves  as  if
       the pattern were *PATTERN*.
...
OPTIONS
       -b, --basename
              Match  only  the base name ....
       ....
       -r, --regexp REGEXP
              Search for a basic regexp REGEXP.  No PATTERNs  are  allowed  if
              this  option  is used, but this option can be specified multiple
              times.

       --regex
              Interpret all PATTERNs as extended regexps.

       -s, --stdio
              Ignored, for compatibility with BSD and GNU locate.
...

şeklindedir.

Örnekler

lifeinbeta@lifeinbeta:~$ locate stdio.h
/opt/lampp/lib/perl5/5.10.1/i686-linux/CORE/nostdio.h
/usr/include/stdio.h
/usr/include/bits/stdio.h
/usr/include/c++/4.4/tr1/stdio.h
/usr/lib/perl/5.10.1/CORE/nostdio.h
lifeinbeta@lifeinbeta:~$ locate -r stdio.*
...
/usr/lib/python2.6/dist-packages/twisted/test/test_stdio.py
/usr/lib/python2.6/dist-packages/twisted/test/test_stdio.pyc
...

şeklindedir.


Linkler

Çok Kullanılan UNIX Komutları

  1. Ten Terminal Commands That Will Boost Your Productivity
UNIX Komut Yapısı
  1. What does {some strange unix command name} stand for?
  2. Which command line commands style do you prefer? – Stackoverflow Polls
Ortam Değişkenleri
  1. PATH ve CLASSPATH ve Java
  2. C ile Ortam Değişkenleri Üzerinde İşlemler
  3. Wiki – Environtment Variables #Ortam Değişkenlerinin hepsi nasıl görülebilir? #Ortam değişkenleri nasıl set edilir? #Bir ortam değişkeninin değeri nasıl okunur?
Shell
  1. Grymoire – UNIX  #Shell #Oldukça kapsamlı referans özellikleri de taşıyan bir Tutorial
  2. Steve Parker Shell Tutorials  #Shell #Daha çok uygulamalı bir Tutorial
  3. Bash Reference Manual #Detaylı, Özellikle Shell İçin bütün açıklamalar
  4. Bash Programming HOWTO #Detaylı
  5. Shell Script’leri ile GUI uygulamaları yapmak #Eğlence
  6. Exit ve Exit Status #Komutların exit status’leri
  7. Bash Koşul İfadeleri  #Detaylı
  8. Bash Conditionals #Sade
  9. Bash Cheatsheet
  10. Çok kullanılan Bash Built-in Komutları
  11. Shell – Command Execution and Simplest Scripts
UNIX Regex
  1. UNIX Regular Expressions – Grymoire
Diğer
  1. UNIX Programming FAQ
  2. GNU All Documentation #GNU Utility‘lerinin Dökümantasyonu

NOT: Bu yazıyı yazarken öğrendiğim şeylerden biri bundan sonra markdown‘ı kullanmam gerektiği oldu.

1 Comment

Filed under UNIX

SSH Ayarları


SSH Nedir?

SSH(Secure Shell) uzak sistemlere girebilmek, ora/ya/dan dosya kopyalayabilmek, firewall’lardan geçebilmek için kullanılan bir alt sistemdir(bir işin belli bölümlerini yapmak için birden fazla uygulamanın oluşturduğu küme). Yapılan bu işlemlerle ilgili veriler ve ayarlar $HOME/.ssh dizininde bulunur. (NOT: tunnelling:yerel bilgisayar ve uzak bilgisayar arası tünel açmayı, belli portları birbirine eşlemeyi, bu konunun dışında tuttum)

UNIX  “. dosyaları”

UNIX’te program genelinde kullanılan bayraklar ve belli başlı değerler, Ortam Değişkenlerinde tutulur. Mesela, java CLASSPATH, JAVA_HOME gibi ortam değişkenlerine sahiptir. Program genelinde ortaklaşa kullanılan veriler fazlalaştıkça, bu verileri tutabilmek için “nokta dosyası”dot file oluşturulur. Bir uygulamanın dot file‘ı o uygulamanın Ortam Değişkenlerine göre daha fazla değer tutar.  Bu değerleri kendi belirlediği belli yazım kurallarına(syntax) göre, hatta programlama dili yapılarını kullanarak, tutabilir.

UNIX “. dizinleri”

SSH bir programdan ziyade bir alt sistem olduğu için ayar seçenekleri (configuration options) fazladır. Bu seçenekleri ve ortak verileri daha düzenli tutabilmek için  .ssh isimli “nokta dizini”(dot directory) ayrılmıştır.(NOT: bu dizinin izin değeri, SSH ın düzgün çalışması için, 600 yapılmalıdır. )

SSH config dosyası

$HOME/.ssh/config dosyasında belli bir uzak bilgisayara bağlanmak için kullanılacak SSH ayarları tutulur. Bu ayarlar config dosyalarının yazım kurallarına göre aşağıdaki gibi tutulur.

Host worker
HostName worker.example.com
IdentityFile ~/.ssh/id_rsa_worker
User joeuser

Yukarıdaki blokta, HostName bağlanılacak olan uzak bilgisayarın adresidir. Host bu adrese verilebilecek bir kısa isimdir. (Bu sayede $ ssh worker.example.com şeklinde yazmak yerine $ ssh worker yazılarak bağlanılabilecek.) Sonraki iki seçenek giriş işlemi sırasında kullanılacak olan kimlik bilgilerini(Credentials – Authentication Info) belirtir. IdentityFile Host(Uzaktaki Bilgisayar) ile Client(Yerel Bilgisayar) arasında yapılacak olan güvenli bağlantıda kullanılacak olan Private Key‘idir.

Başka bir uzak bilgisayar için farklı bir ayar belirtilmek istendiğinde, bir satır boşluktan sonra bu yazı bloğu yeni ayarlarla tekrar yazılmalıdır.

Genel ayarlar bir defa burada belirtildikten sonra aşağıdaki gibi, her bağlantı işlemi için,

ssh joeuser@worker.example.com -i ~/.ssh/id_rsa_worker

yazmak yerine,

ssh worker

yeterli olacaktır.

config dosyasındaki diğer bir kullanışlı seçenek, ControlMaster‘dır. Bu seçenek, aşağıdaki gibi ayarlandığında, belli bir Host‘a yapılacak olan birçok SSH oturumunun, aynı bağlantıyı yani aynı bağlantı ayarlarını kullanabilmesi sağlanır. Dolayısıyla, bir host’a bir defa bağlanıldıktan sonra ona yapılan diğer bağlantılarda şifre sorulmayacaktır.

Host *
ControlMaster auto
ControlPath ~/.ssh/master-%r@%h:%p

Yukarıda “*” ControlMaster’ın auto değerinin bağlanılacak bütün Host‘lar için geçerli olacağını gösterir.

Bunu yapmak için, belli bir host için bir oturum başladığında, SSH önce, bu host için yapılmış, paylaşılan bir bağlantı arar, yoksa yeni bir bağlantı yaratır. ControlPath, bir bağlantının bapaylaşabilmek için bir control socket ini yaratır ve bunu saklar.  ControlPath in değeri çözüldüğünde(resolving, evaluation) bir dosyanın yolunu gösterir.  Yeni oluşturulan control socket burada saklanır.  Dosyanın ismi

master-joeuser@worker.example.com:22

gibidir. Saklanan her control socket için bu şekilde dosyalar oluşturulur. Belli bir host‘a yapılan tüm bağlantılar kesildiğinde bu bağlantıların paylaştığı control socket silinir. Dolayısıyla, herhangi bir anda;

ls ~/.ssh denirse, o anda bağlanılmış olan tüm host‘lar görülebilir.

Ayar bloğundaki %r, %h, %p; ssh config dosyasının kendi dilinin yazım özellikleridir. %r, (r)emote kullanıcı adına; %h, bağlanmak istenen uzaktaki bilgisayar adına, (h)ostName; %p, bağlantı için kullanılacak (p)ort numarasına referans verir. (NOT: %p yerine, yerel bilgisayarda SSH bağlantısı açılıyorsa, %l, (l)ocalhost, kullanılabilir.)

Yazının geneli, Speaking UNIX: Best-Kept Secrets of UNIX Power Users baz alınarak yazılmıştır.

Güzel Sözler

Patience: Think big – implement small. [Sabır: Büyük Düşün – Ufak ufak yapmaya başla 🙂 ]

If not now, then when? [Şimdi değilse, ne zaman?]

Leave a comment

Filed under UNIX