Kahrolsun Bağzı Shell’ler

Ba’ğ’zı şeyler vardır ki ayda yılda bir lazım olur, her seferinde manuelde gezip zaman kaybetmek can sıkıcı. Son 5 yıl içinde 3-4 kez git sunucu kurdum, her seferinde de manuel e ihtiyaç duydum. Unutmamak için aldığım ‘not’ yazılarından biri de bu olacak.

Güvenli Git Sunucu Kurulumu

apt-get install git git-sh ile paketleri kurduktan sonra ‘git’ kullanıcısını debian üzerinde şu şekilde ekliyoruz:
$ adduser --system --home /var/services/git --shell /usr/bin/git-shell --disabled-password git

Burada parametreler önemli.

--system ile kullanıcının “system user” olacağını belirledik ve /etc/skell altındaki .profile gibi dosyaların kopyalanmamasını sağladık.
--home ‘a /var/services/git parametresini geçerek ‘git’ kullanıcısının dizinini /var/services altında olmasını istedik, normal kullanıcılar ile karışmasın.
--shell parametresi güvenlik için önemli “kahrolsun diğer shell’ler”. git kullanıcısı hack’lense bile sadece git işlemleri yapılabilecek, sisteme ulaşılamayacak.
--disabled-password ile “şifre ile giriş yapılamaz” olarak ayarladık. SSH key ile hala giriş yapılabilir, bize de bu lazım. Tabii ki ssh ile normal shell işlemleri de yapılamaz, –shell /usr/bin/git-shell ile bunu da engellemiştik, ssh user@server şeklinde bir giriş mümkün değil.

Özetle, sadece git işlemlerine, sadece ssh key kullanarak yapılmasına izin verdik. Ev dizinini değiştirmemizin bir güzelliği de git@irfandurmus.com:/var/services/git/myblog gibi çirkin/kullanışsız bir yapıyı da engelledik. Geliştiricilerin sadece git@irfandurmus.com:project şeklinde kullanmaları yeterli olacak.

/var/services/git dizin git’in home dizini ve boş. Şimdi repository oluşturalım,
$ cd /var/services/git
$ mkdir myblog.git
$ cd myblog.git
$ git init --bare
$ ls
branches config description HEAD hooks info objects refs

/var/services/git/.ssh/authorized_keys dosyasını oluşturup, içerisine kullandığınız bilgisayardaki ~/.ssh/id_rsa.pub dosyamızı yazıyoruz, bildiğiniz standart ssh key login. (Dosya bilgisayarınızda yoksa ssh-keygen -t rsa ile oluşturabilirsiniz.) Takımdaki diğer arkadaşların id_rsa.pub dosyalarını da ekliyoruz buraya.

Tüm işlemleri root ile yaptığımız için /var/services/git/ dizini altında chown -R git:nogroup . komutunu çalıştırarak yetkileri düzenleyelim.

Hepsi bu kadar, bakalım çalışıyor mu;
$ git clone git@irfandurmus.com:myblog
Cloning into 'myblog'...
The authenticity of host 'irfandurmus.com (***.**.***.***)' can't be established.
RSA key fingerprint is **:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'irfandurmus.com' (RSA) to the list of known hosts.
warning: You appear to have cloned an empty repository.
$ cd myblog/
$ touch foo
$ git add .
$ git commit -am "foo"
[master (root-commit) 9b630ea] foo
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 foo
$ git push -u origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 201 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@irfandurmus.com:myblog
* [new branch] master -> master
Branch master set up to track remote branch master from origin.
$ git remote -v
origin git@irfandurmus.com:myblog (fetch)
origin git@irfandurmus.com:myblog (push)

Happy Coding!

MacPorts ve diğerleri

Homebrew hakkında çok güzel olduğunu iddia eden yazılar gördüm fakat adamakıllı bir kanıt göremedim ben. Homebrew’i aylar önce denedim ve kurduğum ilk gün 3 tane bağımlı paketin olmadığını görünce kırk takla atarak ports a göre döndüm. Kullanacağınız paket yöneticisinde paket zenginliği çok önemli. Kuracağınız paketlerin bağımlılığının olması doğaldır.  Paket yöneticisi seçiminde paket zenginliği en önemli konulardan birisidir.

MacPorts çok yetenekli, neden macports un homebrew den daha üstün olduğunu gösterecek bir kaç örnek vereyim.

Zenginlik

Php 5.3 kullanıyorum, 5.4 ü de sistemime kurmak arada denemek istiyorum. Kullandığım bilgisayarda sudo port activate php54 ile version değiştirip, çalışmayan yer olup olmadığını test edip, herşey düzgün ise sunucuyu da 5.4 e yükseltebiliyorum. Eğer sorun varsa sudo port activate php53 ile önceki versionu aktif edebiliyorum. Aynı şey python veya diğer paketler için de geçerli.

Stabilite

Diyelim ki php5 paketini kurdum. php5 son stabil versiyona linklidir. Yani 5.3 stabil iken 5.3 e linklidir. 5.4 stabil olmuş ise 5.4 e otomatik yükseltilir ve 5.3 sisteminizden kaldırılmaz! Önemli nokta burası. Sistemi güncellediniz, sorun çıktı sudo port activate php53 ile geri dönebilirsiniz.

Ports /opt/local altına kurulur, MacOSX ile birlikte gelen hiç bir uygulamanıza karışmaz, dokunmaz. Kaldırmak istediğinizde de yardım bulması çok kolay.

Sistem Bakımı

Kolay sistem bakımı sağlar. port installed |grep -v “active” ile aktif olmayan paketlerin listesini alıyorsunuz. Baktınız hiç birisi işinize yaramıyor ve bir daha da kullanmayacaksınız. sudo port uninstall inactive ile hepsini kaldırıyorsunuz.

Upgrade / Downgrade

sudo port selfupdate ile sistem veritabanını günceller ve yeni versionları kurarsınız. Debian’daki apt-get update e eşittir. Sorun ile karşılaşırsanız zaten kurulmuş olan eski versionu güncellemek için sadece activate etmeniz yeterli.

Örneğin sunucunuzda php 4.4.9 gibi çok eski bir version var. Karşılaştığınız hatayı kullandığınız bilgisayarda görmek istiyorsunuz. “sudo port install php4 @4.4.9” yazıyorsunuz ve php4 ün 4.4.9 versionu u Macintosh’unuza MacPorts aracılığıyla kuruluyor. Hatayı kendi bilgisayarınızda tekrarlayıp, çözüp commit ediyorsunuz.

Dökümantasyon

En önemli noktalardan biridir dökümantasyon. port help yazıyorsunuz ve şöyle bir çıktı alıyorsunuz (sadece bir kısmı bu).

Supported actions
——————
activate, archive, archivefetch, build, cat, cd, checksum, clean, configure,
contents, deactivate, dependents, deps, destroot, dir, distcheck, distfiles,
dmg, dpkg, echo, edit, exit, extract, fetch, file, gohome, help, info,
install, installed, lint, list, livecheck, load, location, log, logfile,
mdmg, mirror, mpkg, notes, outdated, patch, pkg, platform, portpkg,
provides, quit, rdependents, rdeps, rev-upgrade, rpm, search, select,
selfupdate, setrequested, space, srpm, submit, sync, test, unarchive,
uninstall, unload, unsetrequested, upgrade, url, usage, variants, version,
work

Bunlar sadece action lar. Yani alt komutlar ile bir çok işlem yapabilirsiniz. Daha fazla detay isterseniz kocaman man sayfaları var. homebrew de yardım ı çalıştırınca websitesine yönlendiriyor, ne saçmalık! İnternetim yoksa dökümanım da mı olmayacak?

İnternette Macports’a çok haksızlık ediliyor. Bir sisteme kötü demek için yaşanan problemlerin diğer insanların da yaşayıp yaşamadığına bakmak lazım. Bazı sorunlar “kullanıcı” kaynaklıdır.

MacPorts kullanıyorum, mutluyum. Stabil, başağrısız, bol paketli, güzel dökümantasyonlu bir paket yöneticisi arıyorsanız homebrew, fink gibi atraksyonlara girmenizi hiç tavsiye etmem.

 

Boss ve Git ile nasıl deployment yapılır

Hala FTP ile live server’a dosya gönderenlerin oranı web üzerindeki domainlerin çoğunluğunu oluşturuyor. Revision Control kullananların bir kısmı da doğru sürümleme yapmıyor. Oyunu kurallarına göre oynamak, ürünün sürdürülebilirliği açısından önemlidir.

İşlerinizi otomatikleştirmek, en zayıf halka olan insan hata oranını olabildiğince aza düşürür, size zaman kazandırır. Yazılımınızın deployment stratejisi olması bu noktada önemli. Büyük bir ekip de olsanız, reklam ajansında küçük web siteleri yapıyor da olsanız düzeninizi kurduktan sonra sorunların çok daha hızlı çözüldüğünü göreceksiniz.

Boss Parametreleri

help Yardım dosyasını gösterir
test Local, stage veya live sunucu üzerinde verilen projenin testini tetikler.
deploy Verilen server üzerine verilen projenin verilen sürümünü deploy eder.
rollback Local, stage veya live sunucu üzerinde son yapılan deployment’i geri alır.
project Yeni proje eklemek, listelemek ve silmek için kullanılır.

Deployment

Web dünyasında deployment dediğimiz zaman akla gelen işlemler;

  • Code base update
  • Get pass frontend unit/integration tests
  • Pass backend tests
  • File permission updates
  • Database update (sql/no-sql)
  • Cache invalidation

Bu işlemleri önce kullandığınız bilgisayarda, sonra stage sunucuda son olarak da live sunucuda yaparsınız. Boss‘u ben bu işlemler için kullanıyorum. Farklı deployment yaklaşımları olabilir, size kalmış. Örneğin birden fazla application server’iniz var ise boss size yetersiz gelecektir, henüz çoklu live sunucu desteklenmiyor.

Bir kurulum ile birden fazla proje deploy edebilirsiniz. Sürüm için branch değil tag kullanır, kurulum çok basit;

$ git clone git@github.com/irfan/boss.git boss
$ cd boss
$ sh install.sh

Proje ismi, git repo, projenin bilgisayarınızda ki yolu, stage ve live sunucu bilgilerini girdikten sonra deployment için ilk proje config dosyanız ~/.boss/etc/<projeadi>.conf altında oluşturulacak.

NOT: Bu bilgileri eksiksiz girmelisiniz. sunucudaki proje dizininiz örneğin /var/www altında ise normal user ile burada değişiklik yapamayacağınız için root ssh login’in sunucuda açık olması ve root’u kullanmanız kolaylık sağlar. Eğer normal kullanıcı girerseniz, proje dizininiz /home/irfan altında olsa bile web sunucunuz www-data gibi bir kullanıcı ile çalıştığı için yine sıkıntı olacaktır. Fakat web sunucunuzu ssh ile aynı kullanıcıyla çalıştırıyorsanız sorun yaşamazsınız.

Versioning

Verisyon numaralarının anlamlı olması önemli. Bu konuda düşünceleriniz net değilse Wikipedia daki Software versioning başlığı sürümleme nedir ve nasıl olmalıdır konusunda size ön bilgili verebilir.

Boss sadece tag ile deployment yapabilir. Zaten branch ile yapılan sürümleme işlemi yanlıştır. Bu konu da ayrı bir yazının konusu.

Birinci sürüm deployment

Local, live ve stage sunucunuz da git repository’nizin olduğunu ve git pull yaptığınız zaman git sunucunuzdan güncellemeleri aldığınız bir sisteminizin olduğunu varsayarak devam ediyoruz. HEAD’inizi 1.0.0 sürümü oluşturarark sırasıyla local, stage ve live a deploy edelim.

NOT: Deployment a başlamadan önce .gitignore dosyanıza .boss/* satırını eklemelisiniz. .boss dizini altında deployment ve sürüm logları tutulmaktadır.

$ git status
# On branch master
nothing to commit (working directory clean)
$ git tag
$ git fetch --tags
$ git tag -a 1.0.0 -m "Version 1.0.0 releasing"
$ git push --tags
Counting objects: 1, done.
Writing objects: 100% (1/1), 172 bytes, done.
Total 1 (delta 0), reused 0 (delta 0)
To git@happycoding.net:blog
* [new tag] 1.0.0 -> 1.0.0
$

Bulunduğumuz commit’i yani HEAD’ı 1.0.0 version olarak oluşturduk ve git server’a gönderdik. Şimdi bunu satge a deploy edip testlerimizi çalıştıralım.

$ boss deploy stage blog 1.0.0
==========================================
Deploying to: stage
Project: blog
Version: 1.0.0
==========================================
Pseudo-terminal will not be allocated because stdin is not a terminal.
--> Directory changing
--> creating log directory
fatal: No names found, cannot describe anything.
fatal: No names found, cannot describe anything.
--> Current version is
--> Checking uncommitted changes
--> Fetching tags
--> Pulling with flag
--> Getting new version
--> Setting permissions
Deployment succeed.
Current version is 1.0.0
$

İki tane fatal görünüyor, ilk kez deploy ettiğiniz için bunlar görünüyor. Bir sonraki sürümde görünmeyecek, bunları görmezden gelip devam edebiliriz. Şimdi sıra testlerimizi çalıştırmada.

NOT: Projenizi yapılandırırken testleri trigger edecek scriptin bulunduğu path i ve parametreleri girmiştiniz. Proje dizininizin altında bu scriptin bulunduğunu ve gerekli testleri tetikleyip sonucu verecek yeteneğe sahip olduğunu varsayıyoruz.

$ boss test stage blog
==========================================
Testing on: stage
Project: blog
Version: 1.0.0
==========================================
--> Running 74 frontend tests, please wait
--> 73 of 74 passed
--> 1 test failed:
- Test ID : 12
- Error : User ID could not found in user object
--> Running 138 backend tests, please wait
--> 138 of 138 test passed
Connection to irfandurmus.com closed.
$

Bir testimiz başarısız oldu. Gerekli değişikliği yapıp master branch’a commit edip, sunucuya push’luyoruz. Şimdi bir bugfix yapmış olduk ve bu ayrı bir sürüm olmalı. Sürümümüzün adı 1.0.0-1 olsun.
$ git tag -a 1.0.0-1 -m "12th failed test fixed"
$ git push --tags
Counting objects: 1, done.
Writing objects: 100% (1/1), 173 bytes, done.
Total 1 (delta 0), reused 0 (delta 0)
To git@happycoding.net:blog
* [new tag] 1.0.0-1 -> 1.0.0-1
$

Şimdi tekrar stage e deploy edip testleri çalıştıralım.
$ boss deploy stage blog 1.0.0-1
==========================================
Deploying to: stage
Project: blog
Version: 1.0.0-1
==========================================
Pseudo-terminal will not be allocated because stdin is not a terminal.
--> Directory changing
--> Current version is 1.0.0
--> Checking uncommitted changes
--> Fetching tags
--> Pulling with flag
--> Getting new version
--> Setting permissions
Deployment succeed.
Current version is 1.0.0-1
$

Gördüğünüz gibi stage sunucu üzerindeki sürüm 1.0.0 dan 1.0.0-1 e yükselmiş oldu. Şimdi testleri çalıştıralım.
$ boss test stage blog
==========================================
Testing on: stage
Project: blog
Version: 1.0.0-1
==========================================
--> Running 74 frontend tests, please wait
--> 74 of 74 passed
--> Running 138 backend tests, please wait
--> 138 of 138 test passed
Connection to irfandurmus.com closed.
$

Tüm testlerimiz başarılı olduğuna göre artık live sunucuya bu sürümümüzü deploy edebiliriz.
$ boss deploy live blog 1.0.0-1
==========================================
Deploying to: live
Project: blog
Version: 1.0.0-1
==========================================
Pseudo-terminal will not be allocated because stdin is not a terminal.
--> Directory changing
--> Current version is 1.0.0-1
--> Checking uncommitted changes
--> Fetching tags
--> Pulling with flag
--> Getting new version
--> Setting permissions
Deployment succeed.
Current version is 1.0.0-1

İstersek testlerimizi live sunucu üzerinde de çalıştırıp bir hata varsa aynı şekilde fix edebiliriz fakat stage ile live aynı sonucu vermiyorsa sorun sistemler arasındaki farktadır.

Son olarak belirtmeliyim ki boss kesinlikle bir Jenkins veya Hudson alternatifi değildir, olamazda. Sadece işlerin nasıl olması gerektiğini gösteren basit bir script’dir.

Bash ile temizlik

Sanırım ilk göz ağrım olmasından dolayı bash ile oynamayı seviyorum. Rapidshare’den 10.000 kadar dosyayı toplu olarak zinker ile indirdim.
fakat bazı dosyalar sunucuda bulunmadığı için dosya yerine sunucunun döndüğü hata kodunu kaydetmişiz. Bu bozuk dosyaları bulmak için dosyaların olduğu dizin de;

for file in $(ls); do notzip=`file "$file" | grep -v Zip`; if [ ${#notzip} -gt 1 ]; then echo $notzip; fi; done;

İçeriğine bakmak için;

for file in $(ls); do notzip=`file "$file" | grep -v Zip`; if [ ${#notzip} -gt 1 ]; then cat $file; fi; done;

Silmek için;

for file in $(ls); do notzip=`file "$file" | grep -v Zip`; if [ ${#notzip} -gt 1 ]; then rm $file; fi; done;

Hepsi bu..

Mac OS X Mountain Lion named servisi

Sadece internette hızlı gezmek değil, hosts dosyanıza tanımladığınız domainlere de daha hızlı erişmek için local dns server candır.

Mountain lion da “service” kalkmış, dolayısıyla şurada bahsettiğim yöntem çalışmıyor.

Bunun yerine terminalden

$ sudo rndc-confgen -a
$ sudo launchctl load -w /System/Library/LaunchDaemons/org.isc.named.plist

bu iki kurşunu verdikten sonra, System Preferences e gidip DNS ayarlarınızı 127.0.0.1 olarak değiştirip, ~20 ms daha hızlanmış oluyoruz.

Dediğimiz gibi, not almaktır hayatın anlamı.

ffmpeg ile en basit mp4 yapmak

İnternette konuyla ilgili bir sürü makale görürsünüz, sürüyle parametre, yok o codec bulunamadı, yok bunu kullanamazsın gibi hatalara sebep olabilir.
iPad için en basit ve yeterli yol;

ffmpeg -i myVideo.avi -s 1024x768 myVideoForiPad.mp4
800×600 ekrana sahip bir cihazınız varsa, 1024×768 i 800×600 olarak değiştirin.

Şöyle toplu dosya işlemi de yapabiliriz.

#!/bin/bash
counter=1;
addition=1;
for i in *.avi
do
    ffmpeg -i $i -s 1024x768 "episode-"$counter".mp4"
    counter=$(($counter + $addition));
    mv $i "converted/"$i
done;

Bazen unutmamak için not almaktır hayatın anlamı.

Pratik ssh

Bazen sadece unutmamak için not almaktır hayatın anlamı;
$ vim ~/.ssh/config şeklinde dosyayı açıp aşağıdaki satırları yazıyoruz.

Host myserver
User irfan
Port 9281
HostName irfandurmus.com

SSH’dan makinemize bağlanmak için

$ ssh myserver yazıyoruz, bu komut ssh -p 9281 irfan@irfandurmus.com şeklinde overwrite oluyor.

SSH üzerinden git kullandığımızda da böyle ayarlara ihtiyacımız olmuştu.

Developer’s prompt

Prompt’un ne kadar önemli olduğunu (daha bir kaç yıl önce) farkettiğimde bi’ snippet yazmıştım, geçenlerde github’a push’lamıştım. “Unix like” bir sistemde prompt’da genelde hostname, username felan görürsünüz. Sistemci için “irfan@localhost:~$” gibi bir prompt iyi olabilir fakat bir developer için çok gereksiz veriler bunlar.

Yeterli olduğunu düşündüğüm için geliştirileceğini veya buna ihtiyaç duyulacağını düşünmemiştim, bu yüzden snippets repoma göndermiştim kodu. Bu gün Berker “Bunun sonuna svn de bulunduğumuz branch’i eklesek?” demesiyle bana bi aydınlanma geldi.
(daha&helliip;)

Mac OS X Developer Tools’u kaldırmak

$ sudo /Developer/Library/uninstall-devtools --mode=all
Password:
Start time: Sun Dec 12 01:03:08 EET 2010
Started uninstalling versioned non-relocatable developer tools content.
Shutting down distcc...
Analyzing devtools package: 'com.apple.pkg.VersionedDeveloperToolsSystemSupportLeo'...
Analyzing package: 'BSD.pkg'...
......

Söze gerek yok

MacOS X Terminal renkleri nasıl tanımlanır ve değiştirilir?

MacOS X  Terminal.app da default gelen terminal çok kullanışsız. Terminali ilk açtığınızda beyaz zeminli tüm yazılar siyah renkte, kod renklendirme dediğimiz durum tanımsız (undefined) olarak gelir. Öncelikle Terminal.app i açıp, File -> Preferences -> Startup sekmesinden On startup, open new window with settings kısmını Pro olarak değiştirin. Aynı pencerede Settings kısmından da bazı özelleştirmeleri yapabilirsiniz. Son olarak Shell menüsünden Use Settings as Default u seçin.

İki komutla temel renklendirme işlemlerini yapalım, sonra detaylara gireriz.

echo "export CLICOLOR=1" >> $HOME/.profile
echo "export LSCOLORS=GxFxCxDxBxegedabagDcad" >> $HOME/.profile

Command + Q Tuş kombinasyonu ile terminali kapatıp tekrar açıyoruz, ls -la komutunu verin, evet artık renkli terminal var.

Salatalık özü cilt kreminden önceki ve sonraki hali -P
(daha&helliip;)