4 Nisan 2018 Çarşamba

bash

BASH
Bash ile ilgili bazı notlarım aşağıda
debug
Bash ile en sıkıntılı konu debug etme. Debug edilecek kod -x ile ekranda görülebiliyor.
#!/bin/bash

set -x
..code to debug...
set +x

subshell
() şeklindeki kodlar subshell içinde çalıştırılır
#!/bin/bash

function bla() {
    return 1
}

bla || ( echo '1' ; exit 1 )

echo '2'
Eğer komutların kendi kabuğumuzda çalışmasını istiyorsak {} içine almamız gerekir.

(list)
 list is executed in a subshell environment. Variable assignments and builtin commands that affect the shell's environment do not remain in effect after the command completes. The return status is the exit status of list.
{ list; } list is simply executed in the current shell environment. list must be terminated with a newline or semicolon. This is known as a group command. The return status is the exit status of list. Note that unlike the metacharacters ( and ), { and } are reserved words and must occur where a reserved word is permitted to be recognized. Since they do not cause a word break, they must be separated from list by whitespace or another shell metacharacter.


Parameter Expansion
Parameter Expansion bash'in en önemli özelliklerinden birisi. Aşağıdaki şekilde parameter expansion işleminin bir kaç kademeden oluştuğu görülebilir.
[Bash Component Architecture]

Brace Expansion
Sonu 1'den 100'e kadar devam eden 100 tane dizin yaratmak için brace expansion kullanılabilir.
mkdir subdirectory_{1..100}
Parameter Expansion
Bir değişkene değer atadıktan sonra tekrar değer okumak için $MyVariable şeklinde kullanırız. Yani dolar işareti ve değişken ismi şeklinde. Ancak değişkenin değeri bash tarafından bazı işlemlere tabi tutulur. Bu işlemlerde şuna dikkat etmek gerekir.

Değişkeni Çift Tırnak İçinde Kullanmak Gerekir!
Bash bize sunu söyler. Çift tırnak içinde olmayan değişkenlerin değeri kelimelere ayrılırlar. Eğer değişkenimizin değeri tek kelime ise sorun çıkmaz. Örneğin şöyle bir kopyalama komutumuz olsun.
cp -r $pck_dir"/*" $TAR_DIR"/pck/"
Eğer pck_dir arasında boşluk olan bir değere sahipse bash iki kelimeye ayrılır.

"An unquoted variable will be subject to word splitting. So, if pck_dir had the value my dir, then $pck_dir"/*" would be expanded to two words my and dir/* and both words would be passed to cp as separate arguments. Unless you want word splitting, shell variables should always be in double quotes."
Dolayısıyla cp komutuna tırnak içinde değişken geçilmeli
cp -r "$pck_dir"/* "$TAR_DIR/pck/"
Değişkenin Kendi İsmini Kullanmak İçin Tek Tırnak Kullanmak Gerekir
Bunu basit bir C kodu ile görmek mümkün. Eğer uygulamamızı şöyle çalıştırırsak
./a.out '$6$4MfvmFOaDUaa5bfr$cvtrefr'
Aynen verdiğimiz şeyi alırız. Eğer şöyle çalıştırırsak
./a.out $6$4MfvmFOaDUaa5bfr$cvtrefr
bash $6 ve $4 için expansion yapar. Bu değerleri bulamadığı için bize parametre olarak MfvmFOaDUaa5bfr$cvtrefr gelir. Şu kod ile sonucu teyit edebiliriz.
char *str = malloc(strlen(argv[1]) + 1);
strcpy(str, argv[1]);

printf("%s\n", str);
Çıktı olarak 
MfvmFOaDUaa5bfr
alırız. Yani değişken etrafındaki tek tırknak ve çift tırnak farklıdırlar.

Parametreye Harf Eklemek
Örnekte ${MyVariable} şeklinde kullanılarak kelime çoğul yapılmış.
echo "I like to eat ${fruit}s"

File Expansion
Bash File Expansion yazısına taşıdım.

Bash Çalıştırma Seçenekleri
bash -e seçeneği ile kullanılırsa, ilk başarısız işlemde betik durdurulur. Başarısız işlem herhangi bir
işlemin 0'dan farklı bir değer dönmesidir. Örnek:
#!/bin/sh
set -ex
if koşulu
bash if koşulu yazısına taşıdım.

while döngüsü
while kontrol komutu
do
   diğer komutlar
done örüntüsünü takip eder. Örnek

who | cut -d " " -f 1| sort -u |  while read user
do
  echo "Hi there!" | mail $user
done
Bir başka örnekte while true döngüsü var.
#!/bin/sh
n=
while true
do
    fname="trace$n.log"
    [ -f "$fname" ] || break
    n=$(($n+1))
done
traceroute google.com >"$fname"

fonksiyon yazma
Örnek'te bir fonksiyon yazılıyor. Geçilen parametrelere $1'den başlayarak erişilir.
function running {
  pgrep -f "$1" &> /dev/null
}
bash betiklerinde function kelimesi olmadan da fonksyion yazılabiliyor. Bir çok programlama dili C'den türediği için func, def vs. gibi fonksiyonun başlangıcında bir anahtar kelime gerektirir. Bash istinai bir şekilde function kelimesini isteğe bağlı bırakmış.
running() {
    pgrep -f "$1" 2> /dev/null
}
Fonksiyonumuza parametre geçmek için () karakterlerine ihtiyaç yok.
if ! running mysql; then
    mysql.server start
  else
    echo "MySQL already running"
fi
basename
Verilen yolun son dizin ayracından sonra kalan son kısmını verir. Eğer ikinci bir parametre verilirse uzantıyı da döndürülen sonuçtan çıkarır
Print NAME with its trailing /component.

Örnek
basename /home/myfolder.sh .sh çıktı olarak myfolder verir

Örnekte .sh ile biten bir script ile aynı isme sahip bir dosyayı çalıştırmadan önce local .so kütüphaneleri arama dizinine ekleniyor.
#!/bin/bash
appname=$(basename "$0" .sh)
dirname=$(dirname "$0")
cd "$dirname/bin"
export LD_LIBRARY_PATH=$(pwd):$LD_LIBRARY_PATH
./$appname "$@"

dirname
Verilen yolun son dizin ayracından önceki kısmını verir.
Print NAME with any leading directory components removed. Örnek
dirname /home/myfolder çıktı olarak /home verir.


Bir nesnenin var olduğunu kontrol etmek (file test operators)
Konuyu bash file test operators başlıklı yazıya taşıdım.

Başka Bir Komutu Çalıştırmak
Çalıştırmak istenilen komut parantez içine alınırsa yeni bir kabuk içinde çalıştırılır. Örnek
(pwd)

read
Verilen girdiyi stdin'den parçalayarak okur.
Örnek:
$ IFS=";"

$ read first second 
i am;a_i b c
$ echo $first
i am
$ echo $second
a_i b c

source
Bir bash betiği başka bash betiğini çağırılınca yeni betik farklı bir kabuk içinde çalıştırılır. Örnekte
#!/bin/bash
${HOME}/.ssconfig
echo "Hello, ${VARIABLE}!"
betiği ssconfig.sh betiğini çalıştırıyor. ssconfig betiği ise bir değişkene değer atıyor.
#!/bin/bash
VARIABLE=world
Fakat ssconfig yeni bir kabuk içinde çalıştığı için kendisini çağıran betik çıktısını çıktı olarak
"Hello, !" veriyor. Yeni betiğin source komutu ile çalıştırılması gerekir.
#!/bin/bash
source ${HOME}/.ssconfig
echo "Hello, ${VARIABLE}!"
Source bash içinde bir komuttur. Dolayısıyla man source ile değil help source ile yardım alınabilir. Açıklaması şöyle:
$ help source  
source: source filename [arguments]  
    Execute commands from a file in the current shell.

    Read and execute commands from FILENAME in the current shell.  The
    entries in $PATH are used to find the directory containing FILENAME.
    If any ARGUMENTS are supplied, they become the positional parameters
    when FILENAME is executed.
source komutuna eşdeğer bir diğer seçenek ise include komutu. Örnekte bir başka betik aynı kabuk içinde çağırılıyor.
$include  /etc/inputrc

Dosyaları Dolaşmak
Dosyaları bir değişkene aldıktan sonra for döngüsü ile dolaşmak mümkün. Örnek:
val1=$(date +%Y%m%d --date="yesterday")
FILES=`ls ./*$val1.log`
for f in $FILES
do
    clear
    cat $f
    sleep 10
done

bat dosyası
bat dosyasında kullanılan bazı komutlar aşağıda.

Java HOME
Java kurulum dizininde boşluk varsa Program Files yerine aşağıdaki kısaltmalar kullanılabilir.
Progra~1 = 'Program Files'

Progra~2 = 'Program Files(x86)'

for döngüsü
Örnek'te verilen yol dolaşılarak her dizine bir alt dizin açılır.
FOR /d %A IN ("C:\Main Folder\*") DO mkdir "%A\Family Members"
Şöyle yaparız.
@echo off
for /L %%N IN (1, 1, 200) DO (
    ping -n 1 192.1.22.%%N
    if not ERRORLEVEL 1 (
        set pingresult=true
        goto done
    )
)

set pingresult=false
:done
if %pingresult% == true (
 echo Pikachu


) else (
  echo "Offline!"
)
boolean logic
boolean logic mevcut değil. Or ve And işlemleri yok. Dolayısıyla if/else yazmak sıkıntı. Aşağıdaki C kodu 
if(version == 1 || version == 2)
{
   // do something
}
else
{
   // do something other
}
şöyle yazılabilir.
if "%version%"==1 (
 // do something
)
if "%version%"==2 (
 // do something
)
if not "%version%"==1 (
   // do something other
)
if not "%version%"==2 (
   // do something other
)
veya goto kullanılabilir.
if "%version%"=="1" goto :TRUE
if "%version%"=="2" goto :TRUE
REM do something else

echo neither 1 or 2 :(
goto :eof

:TRUE 
REM do something
echo 1 or 2 :)

komut satırı parametreleri
bat dosyasını çağırırken verilen parametrelere %1% , %2% şeklinde indeks numarası ile erişilir.

if %1% == "A" mycommand
if %1% == "B" myothercommand

dosya kopyalama
xcopy kullanılabilir
/S boş dizinler hariç tüm dizin ve altdizinleri kopyalar
/Y hedef dosyalar varsa üzerine yazar
/I hedef  dizin yoksa yaratır

dizin değiştirme
/d seçeneği ile disk değiştirmek mümkün.
cd /d "E:\Program files\MyDirectory"

dosya silme
Örnek:
1del /f

dizin silme
rd /S /Q src

dizin yaratma
md bin

dosya uzantısı değiştirme
Dizindeki tüm dosyaların uzantısını dğiştirmek için ren (rename) kullanılır.
ren *.h *.cs

echo
@ECHO OFF - dosyanın başına konulur ve komutların ekrana yazılmasını engeller.

pause
@echo off
set VA=Two
echo %VA% people
pause
Press any key to continue yazar ve bekler

run as
Bir bat dosyasını administrator olarak çalıştırmak için önce shortcut oluşturulur. Daha sonra kısayayola sağ tıklanarak Advanced sekmesinde Run As Administrator seçeneği seçilir.

start
Konuyu nohup başlıklı yazıya taşıdım.



 

Hiç yorum yok:

Yorum Gönder