Emre.xyz

@delirehberi thoughts

bu yazı ilk olarak medium üzerinde yayınlanmıştır

Hunharca tartışılan Türkiye’de yeni mezun bilgisayarcı (burada yazar yazılım mühendisi olmak isteyen tüm çaylakları kastetmektedir) kişiler için başlangıç maaşının ne olması gerektiği konusunda iki kelam etmeye çalışacağım.

Yeni Mezun

Yeni mezun derken ikinci harf olan e’yi uzatmanız önemli. Yeni Meeezun, derken neden bahsediyoruz bunu bir sınıflandıralım. Okuduğu okuldan bağımsız olarak amacı yazılım geliştirme uzmanlığı olan, “Ben de kod yazmak istiyorum” diyen değil “Ben de kod yazarak para kazanmak istiyorum” diyen kişilerdir. İlla ki okullu da olması gerekmez bu şahsın. Yazılımcı olarak ilk deneyimini kastediyoruz. Okullu olanlar burada kalkıp ben onca sene okudum niye aynı sayıyorsunuz demesin. Çünkü okuduğunuz okullarda aldığınız eğitimden daha iyi seviyede olan alaylılar da mevcut. Yani okul sizin yazılım bilginize “fazladan” bir şey katmaz. Size mühendislik disiplini katar, bu da aşağıda bahsedeceğim formülün bir başka değişkenidir. Ancak her okulluya da aynı muamele yapılamayacağı için, okullu ve alaylı aynı potada eriyecek yazı boyunca.

İlk İş

‘Yazılım’ sektörü dışında dahi ilk işine başlayan kişi eğer öğrenimi sırasında herhangi bir sektör içi tecrübesi yoksa en iyi ihtimalle (devlet memurluğu dışında) ilk başlayacağı iş için asgari ücret neyse o ücreti kazanmaya başlayacaktır. Burada fen veya sosyal bilimler alanında eğitim görmüş ve araştırmacı diyebileceğimiz kişileri ayrı tutuyorum. Çünkü bu kişiler için iş olayları çok daha farklı cereyan etmektedir. Yazılım sektöründe ise iş biraz daha karışık. Kişinin sektör tecrübesi olmasa dahi, açık kaynak dünyaya katkı sağlamış olabilir ve/veya kişisel projeleri mevcut olabilir. Bu sayede direkt olarak sektör içinde olmasa dahi yetkinlik kazanmış bulunabilir. Bu sebeple ilk iş tabiri yazılımcı için biraz bulanıktır.

Bu sebeple zaten bu kadar çok kafadan (biri ben) bu kadar çok farklı ses çıkmaktadır. Ancak sığ kişiler tümünü aynı kefeye koydukları için çok fazla yanlış fikir oluşuyor. Zaten bu yazının ana sebebi bu.

Peki Maaş Ne?

Evet, esas soruya cevap vermedim hala. Çünkü yukarıda da dediğim gibi basitçe şu olmalıdır gibi bir durum mevcut değil. Eres olarak bizim kişisel deneyimlerimize dayalı bir formulümüz mevcut, bizim gibi bir sürü farklı şirketin de kendi deneyimlerine dayalı fiyat politikaları mevcut.

Bizim Formül

Maaş bizim için zaman değeridir en başta. Bir çalışana ödeyeceğimiz ücret ne kadar zamanını alacağımızla başlıyor. İlk değişkenimiz satın aldığımız zaman. Buradaki zamanı ön tanımlı olarak 1 aylık çalışma süresine yapacağı işten bağımsız olarak asgari ücret olarak ekliyoruz. Asgari ücretten başlamış oluyor hesabımız kısaca.

Ardından bu kişinin bize katacağı ve bizden alacağı zamanı hesaba katıyoruz. Şöyle ki bu kişinin yeterliliği sıfır noktasında değilse, yani atadığımız işleri çözebilmek için bir başka çalışanın vaktinden çalacak yani iş öğrenecekse değer katarken, bu kişinin ortalama aylık çalabileceği vakti hesaba katıyoruz. Burada hem kişinin yeterlilik seviyesi, hem öğrenme kapasitesi etkili. Aynı bilgi seviyesine sahip iki kişiden birisi tek seferde anlatılanı anlayabilir; farz edelim aylık, usta yazılımcıdan çalacağı vakit %5`tir, ancak diğer bir kişi hem anlatıma hem uygulamalı gösterime ihtiyaç duyar, bu kişinin ise çalacağı vakit %20 olacaktır. Çıkan yüzde oranını ilk değer olan asgari ücretten düşüyoruz. Ancak eğer kişi herhangi bir kişiden zaman çalmayacak ve self-learning ile kendisi çözüp üzerine verilen işleri rahatlıkla çözecek ve ustasına fayda sağlayarak iş çözebilecek ve bize ekstra zaman kazandırabilecekse, tahminen sağlayacağı iş gücünü ustasına göre %10 diyelim örneğin, asgari ücretin üzerine ekliyoruz.

Temelde bu şekilde kişinin sağlayacağı katkı oranını hesaba katarak, kısaca tamamen ticari düşünerek başlangıç ücretini belirliyoruz. Ancak bu noktada bahsetmediğim içgüdüsel değişkenler de mevcut. Tecrübesiz kişiyi işe alarak şirketlerin aldığı riskler de mevcut. Bahsettiğim şekilde asgari ücretten başlatıyoruz ve bunu geleceğe yatırım olarak düşünerek yapıyoruz. Yani asgari ücret ile başlayan kişi hiçbir şey yapmadan da üç ay boyunca maaş alıp sonra vazgeçtim ben diyip gidebilir, ya da çok fazla diğer personelden vakit çalıp edinimlerini sağlayıp tamam ben alcağımı aldım deyip gidebilir. Yani şirkete tam fayda sağlayacağı noktada bırakıp gidebilir. Bu durumda şirket zarara uğraşmış olacaktır.

Mülakatlarda bu gibi durumlar içgüdüsel olarak tahmin edilmeye ve ilk işi olacak kişi için risk analizi yapılır, bu da belli bir yüzde olarak maaş belirlemede kullanılır.

Son olarak bir de (sonunda) kişinin maaş beklentisi vardır. Bu sadece kişi hakkında yukarıda bahsettiğim risk analizi hesabı için kullanılacak bir bilgi sunar. Bu demek değil ki az maaş isteyin risksiz görünün. Dengeyi yakalaması önemlidir kişinin. Kendi yeterliliğinin çok altında maaş isteyen birisi de risklidir şirket için, aksine kendinin farkında olmayan bir kişi de 6 ay sonra kaçma ihtimalini bulundurabilir. Yani maaş beklentinizi kendinize göre “benim zamanımın şu anda değeri bu kadardır” der gibi söylemeniz gerekiyor. Bu da hesaba dahil ediliyor.

Yukarıdaki hesap dışında çok sık karşılaşılmasa da ekstrem durumlar mevcut. Örneğin henüz mezun olmadan iş teklifi götürebildiğimiz insanlar da mevcut. Şöyle ki kişisel olarak işini fazlasıyla sevmiş ve para için yapmasa bile işler çıkartmış açık kaynak olsun olmasın işlemiş kişiler her şirket için olduğu gibi bizim için de değerlidir. Bu gibi kişilere tamamen (gerçeklikten uzaklaşmadan) kendilerinin belirlediği maaşları ödüyoruz. Üstelik tam zamanlı çalışan olup olmamak da değil, outsource veya remote olarak da çalışabiliyoruz. Tabii bunlar yaptıkları iş konusunda para için hiç iş yapmamış olsa dahi parlak gelecek vaadeden kişilerdir.

Net bir şey söyle

Net tek rakam asgari ücrettir, bunun üstünde bir kişiye sırf o işe girmek istediği için “minimum şu kadar ücret ödenmelidir” demek abesle iştigaldir. Çünkü her insanın amaçları, seviyesi, yetkinliği, kazandırdıkları farklıdır. Çıkıp boş konuşarak şu maaştan aşağı başlamayın diyerek hadsizlik etmek kimsenin hakkı değildir.

Neden?

Herkes aynı işi aynı şekilde yapmaz, o yüzden herkesi aynı kefeye koyamazsınız, sırf aynı mesleği icra etmeye niyetlendi diye. Sadece bir alt limit belirlersiniz ki bu noktada bu asgari ücrettir. Bu da her sektöre uygulanır sadece yazılımcılara özel değildir. Sektöre yeni girmiş birisi sadece günlük harçlığı karşılığında Serdar Doğruyolla beraber çalışmak ve onun zamanına karşılık kendi zamanını vermek isteyebilir ki denk değildir bu sebeple üstteki formülde olduğu gibi Serdar’dan, Fatih Arslandan yahut Gökhan Şengün`den uzmanlıkları hakkında günlük bir saat bilgi almak 3–5 ay boyunca alacağı maaşdan çok değerli olabilir.

Bir de Serdar`ın, tartışma hakkında en beğendiğim yorumunu şuraya iliştireyim.

Daha da ötesinde kalkıp “başlangıç maaşı şu kadar olmalıdır” diyenlere itibar etmeyiniz. İşinizi ne kadar iyi yapıyorsanız o kadar iyi kazanacağınızdan emin olun. Kendinizi bilin, 6 ayda bitiremeyeceğiniz 50.000 liralık proje için aylık 5.000 lira isterseniz kimse sizi ciddiye almayacaktır. Aynı şekilde şirkete müthiş katkı sağlayacağınızı iddia edip “asgari ücret yeter abi” dediğinizde de kimse sizi ciddiye almayacaktır.

Kendinizi bilin, işinizi iyi yapın. Henüz yola yeni çıkıyorsunuz, ilk derdiniz maaş olursa o yol hayal ettiğiniz yere çıkmayacaktır.

#tr #oneri

Son bir kaç aydır Haskell öğrenmeye çalışıyorum. Neden böyle bir maceraya giriştiğimle ilgili bir yazı yazmak istiyorum ilerde.

Şimdilik öğrendiğimi düşündüğüm konuları hem not etmek, hem de türkçe kaynak oluşturmuş olabilmek adına, olabildiğince bloguma eklemeye çalışacağım.

Functor, Haskell'de bir TypeClass olarak tanımlanmıştır. Yaptığı iş, kapsayıcıya/kapsama (context) müdahale etmeden, içerdeki veride işlem yapabilmeye olanak sağlamaktır.

Basitçe toplama işlemi için (+3) 2 dediğimizde, 2 ile 3 ile toplayan fonksiyonu işleme sokarak 5 sonucuna ulaşmış oluyoruz. + iki argüman bekleyen bir fonksiyon olduğu için birinci fonksiyonu vererek 3 ile toplayan fonksiyona çevirme işlemine currying deniyor. Başka bir yazıda detaylıca gireceğim.

Ancak contexte müdahale etmeden işlem yapmak istediğimiz zamanlar olacaktır. Örneğin; HaskelldeMaybeadında birtypemevcut.Justile kapsanmış bir değer yahutNothingdeğerine sahip olabilir. Eğer elimizdeMaybe Inttüründe birJust 2değeri varsa bunu(+3)fonksiyonumuza nasıl verebiliriz?+fonksiyonu iki argüman bekliyor, ikisi deNum` olmalı. Ancak birisi doğruyken diğeri bir kapsayıcı içerisinde.

Üstelik biz işlem sonucunda elimizdeki Just 2 değerinin türünün değişmesini istemiyoruz.

Çok şanslıyız çünkü Maybe türü bir Functor.

Peki bir Functorı nasıl işleme sokabiliriz? Elimizdeki Functorlar ile işlem yapmamız için çok güzel bir fonksiyon var ve adı fmap.

Bir Functor ile işlem yapmak istediğimizde, fmap fonksiyonunu kullanabiliriz. Örneğin; fmap (+3) (Just 2) dediğimizde bize sonuç olarak Just 5 verecek ve kapsayıcımız bozulmamış olacak.

Maybe türü için Functor tanımlaması ise şöyle yapılmış durumda:

instance Functor Maybe where
    fmap func (Just val) = Just (func val)
    fmap func Nothing = Nothing

Gördüğünüz gibi net bir şekilde Functor typeclassından tanımlanmış instancelar ile Functorların fmap fonksiyonu ile nasıl çalışabileceği belirlenmiş durumda. Tüm Functorlar için instancelar bu şekilde tanımlanmıştır. Maybe için eğer beklenen değer Nothing gelirse verilen fonksiyon uygulanmadan Nothing dönmektedir.

Ayrıca Haskell'de listeler de birer Functor instanceına sahiptir. Bunu da diğer yazıda paylaşacağım.

#haskell #tr #functor #functionalprogramming #fonksiyonelprogramlama

Bir önceki yazıda belirttiğim unix türevi sistemlerde efektif çalışma konusunun bir tık ilerisine girdi-çıktı yönlendirme konusunu koyabiliriz. Bahsettiğimiz pipe(|) işlemi aslında bir girdi-çıktı yönlendirme operatörüdür. Önce terminalde girdi-çıktı türlerine bakıp nasıl ve neden yönlendirebiliriz bir görelim.

İlk bilmeniz gereken şey unix türevi sistemler üzerinde bulunan her şeyin birer dosya olduğudur. Tüm klasörler, linkler, cihaz bağlantıları vs birer dosyadır. Harddisk bir dosyadır, webcam bir dosyadır, ses kartı bir dosyadır.

Her dosyanın ne olduğunu belirten bir file descriptor olarak ifade edilen tanımlayıcısı vardır. Pozitif sayılardan oluşabilen bu değer dosyanın ne olduğunu belirtir. 3 adet standart file descriptor mevcuttur. 0,1,2 olarak belirtilmiş sayılar sırasıyla stdin, stdout, stderr olarak belirlenmiştir. 0 dosyanın (herşey dosya olduğu için girdi ve çıktılar da dosyadır) standart bir girdi olduğunu, 1 dosyanın standart çıktı olduğunu, 2 ise dosyanın standart hata olduğunu gösterir.

Yani biz cat komutunu parametre vermeden çalıştırdığımızda sonuç olarak stdin türünde bir dosyamız oluyor. Standart girdi türü haliyle bizim veri girmemizi bekliyor.

Eğer echo "xyz" komutunu çalıştırırsak stdout türünde bir dosya üretmiş oluyoruz. Ekrana xyz basmış oluyor.

Son olarak ls /xyz komutunu çalıştırdığımızda ise stderr türünde bir dosya üretmiş oluyoruz ve ekrana hata basılıyor.

Geçen yazıda gördüğümüz pipe üzerinden basit bir örnek yapabiliriz. ls /var/log/syslog ve sed "s/syslog/xyz/" komutlarını birleştirerek ufak bir işlem yaparsak sonuç olarak ekranda /var/log/xyz çıktısını göreceğiz.

$ ls /var/log/syslog|sed "s/syslog/xyz/"
/var/log/xyz

Pipelining bu kadardı zaten. Bir çıktıyı al diğer uygulamaya girdi olarak ver. Fakat eğer ls /var/log/emre.xyz|sed "s/syslog/xyz/" komut çalıştırırsak ne olur? Hata verecek ve sed komutu çalışmayacak değil mi? Hayır, sed komutumuz her durumda çalışacak. Çünkü mantıksal bir işlem yapmıyoruz. Peki o zaman, sed komutu çalışıyor ise, hata mesajındaki bir şeyi değiştirebilir miyiz?

ls /var/log/emre.xyz|sed "s/syslog/xyz/"
ls: cannot access '/var/log/emre.xyz': No such file or directory

Hata mesajımızdaki cannot kısmını değiştirmek isteyelim örneğin. ls /var/log/emre.xyz|sed "s/cannot/xyz/" komutunu çalıştırmamız gerekecek.

ls /var/log/emre.xyz|sed "s/cannot/xyz/"
ls: cannot access '/var/log/emre.xyz': No such file or directory

Fakat o da ne? sed hata mesajını görmüyor. Çünkü sed in beklediği şey stdout fakat ekrandaki hata mesajı stderr türünde. Bu sebeple sed bu mesajı görmezden gelecek.

Peki nasıl yapacağız? İşte konumuza geldik. Bir türü diğerine yönlendirmemiz gerekecek.

Daha mantıklı bir senaryoda ise, yaptığınız tüm işlemlerin sonucunu bir dosyaya yazmak isteyebilirsiniz. Hata mesajını ya da başarılı işlemleri bir yere yazabilmek için de yine çıktı yönlendirme yapmanız gerekecek.

Girdi – çıktı yönlendirme yapabilmek için kullanabileceğiz 6 adet operatör mevcut. Tabi ki sadece 6 tane değil. Ancak biz 6 tanesinden bahsedeceğiz sık kullanılabilecek olanlar olarak. Hepsini hızlıca birer örnek ile göreceğiz. >,<,>>,<<,<&,| olmak üzere 6 adet operatör mevcut.

Şuraya gönder operatörü >

echo "hello world" > dosya.md şeklinde kullanılıyor. Sol taraftan gelen stdout çıktısını dosya.md adında bir dosyaya yönlendiriyor. stdout bekleyen her yere yönlendirme yapabilirsiniz.

Şuradan al operatörü <

grep "awesome" < ls *.aww şeklinde kullanılıyor. Sağ taraftan gelen stdout verisini sol tarafa parametre olarak yönlendiriyor.

Şuraya göm operatörü >>

echo "hello" >> msgs.md şeklinde kullanılıyor. Sol taraftaki çıktıyı sağ taraftaki dosyaya ekliyor. > tüm çıktıyı eski veri var ise üzerine yazarken >> üzerine yazmak yerine eski verinin yanına ilişitiriveriyor.

Şuradan getir operatörü <<

grep 'dene' << MSG
> deneme
> dene
> densiz
> MSG

Şeklinde kullanılıyor. stdin kaynağına yönlendirmeyi sağlıyor. Operatörden sonra verilen kelimeyi görene kadar stdin sizden veri bekliyor, kelimeyi gördüğünde işleme başlıyor. Bu operatör en çok bash dosyaları yazarken işinize yarayacaktır.

Şunla birleştir operatörü >&

ls / 1>&2 |sed 's/bin/can/' şeklinde kullanılıyor. Normalde stdout olarak verilen çıktıyı stderr olarak çeviriyor. Bunu hata verse de stdout olarak işlemek istediğiniz yerlerde kullanabilirsiniz. Yukarıda bahsettiğimiz ls /var/log/emre.xyz|sed "s/syslog/xyz/" komutundan dönen hata mesajını artık şu şekilde kullanabiliriz.

ls /var/log/emre.xyz 2>&1|sed "s/cannot/xyz/"
ls: xyz access '/var/log/emre.xyz': No such file or directory

Şundan al buna ver |

Bunun üzerinden tekrar geçmeyeceğim. Sol taraftaki stdout u al sağ tarafa stdin olarak ver işlemi için kullanabileceğinizi zaten biliyorsunuz.

Unix tabanlı işletim sistemi kullanıp nimetlerinden faydalanmayan çok insan görüyorum. Özellikle araştırmacı olup windows'a yahut macos'un arayüzüne mahkum olanlar için hızlıca unix felsefesinden bahsederek nasıl işlerinizi daha etkili bir şekilde halledebileceğinizi anlatmaya çalışacağım.

Unix Felsefesi

Unix felsefesi formal bir felsefe değildir. Tecrübeyle geliştirilmiş bir felsefedir. Kusursuz uygulama nasıl yapılır diye bir şey söylemez ya da bir uygulamayı nasıl yapmanız gerektiğiyle ilgilenmez. Unix felsefesi tüm sistemi oluşturan parçalara odaklanır ve bütünleşme üzerine fikirler yürütür.

Unix felsefesinin temelleri şöyledir¹:

  • Bir uygulama sadece tek bir şeyi iyi yapmalıdır. Bir iş için yeni bir uygulama yapmak, eski uygulamaya özellik ekleyip karmaşıklaştırmaktan daha iyidir.
  • Bir uygulamanın vereceği çıktı, diğer bir uygulama için girdi verisi olarak kullanılabilmelidir. Çıktıyı gereksiz detay bilgileri ile kirletmeyin. (Detay bilgi dönmesi gerekebilen uygulamalar için -v parametresi ile verbose mod desteği ekleyerek uygulamanın arzu edilirse detaylı çalışmasını sağlayabilirsiniz. Ya da başka bir parametre ile.)
  • Bir uygulama interaktif girdi beklememelidir. Girdilerini parametre ile ve/veya stdin (başka bir program çıktısı) üzerinden alabilmelidir.

Pipeline

Temel unix felsefesini oluşturan kuralların işleyebilmesi için bilinmesi gereken en önemli şey “Pipe”(|) işaretinin yaptığı iştir. Çünkü bir programın başka bir programdan girdi alarak ilerleyebilmesinin, yani birleştirilebilir olmasının yöntemidir. Türkçe klavyeler için alt işareti ile beraber - işaretine basarak ulaşabilirsiniz. Tam olarak yaptığı iş, solundaki program ne dönerse bunu al sağdaki arkadaşın girdisi olarak kullan.

En basit uygulamalardan birisi ls ile bir örnek yapmak için wc uygulamasını kullanabilirsiniz. ls bulunduğunuz klasördeki veya verdiğiniz klasördeki dosya ve klasörleri listeler, wc ise verilen girdide kelime sayma işlemi yapmanızı sağlar.

ls /usr/bin/|wc -l

Yukarıdaki örnek benim bilgisayarımdaki /usr/bin klasöründe 2369 adet dosya olduğunu söyleyebiliyor. ls e parametre olarak verdiğim klasör her satıra bir dosya-klasör çıktısı olacak şekilde bir metin üretiyor. wc ise -l parametresi ile satırların sayısını istediğimi söylüyor. Sonuçta bana klasörde kaç dosya olduğunu söyleyen bir uygulama elde etmiş oluyorum. İki programın da yapmak için planlanmadığı bir program çıktısı oluştu.

Birisi dosya-klasör gösteren, diğeri ise verdiğin metinde sayma yaparım diyen iki programı birleştirerek, istediğin klasördeki dosya-klasör sayımı yapmamı sağlayan bir program programlayabilmiş oluyorum.

Unix felsefesinin en temelindeki fikir budur.

Mantıksal işlemler

Terminal üzerinde mantıksal işlem yapabilmenize imkan sağlayabilen oparatörler mevcut. AND ve OR işlemler yapmak istediğiniz zaman && ve || operatörlerini kullanabilirsiniz. Yan yana iki uygulama çalıştırmak istiyorsanız ve birbirlerinden bağımsız hareket etsin isterseniz de ; operatörünü kullanabilirsiniz.

Örneğin: cd /missing/dir && ls komutunu çalıştırırsanız ilk komut çalışmayacağı için ikinci komut es geçilecektir. Ancak cd /missing/dir || ls dediğinizde soldaki komut çalışmasa bile ls komutu çalışacaktır.

MAN

Tabi ki unix tabanlı işletim sistemlerinde bu kadar küçük parçalardan oluşan yüzlerce-binlerce küçük uygulama bulunmaktadır. Hepsinin nasıl çalıştığını bilmeniz mümkün değil. Bu yüzden man adında bir uygulama daha mevcut. Geliştirilen uygulamalar için hazırlanmış yardım dökümanlarını görüntülemek için kullanabilirsiniz.

Örnek olarak man ls yazıp çalıştırırsanız, size ls uygulaması hakkında tüm detayı verecektir. Hangi parametreyi alır, hangi işleri yapar, nasıl kullanılır gibi.

Eğer küçük bir hilekarsanız, “bu dökümanlar çok uzun, nasıl kullanıldığını bilsem yeter” derseniz diye tembel yazılımcıların oluşturduğu hile servislerini kullanabilirsiniz. Örnek olarak cheat.sh size yardımcı olabilir. Bunun için curl adındaki, internetten veri almanıza olanak sağlayan bir uygulamayı kullanabilirsiniz.

curl cheat.sh/ls komutunda olduğu gibi adres satırının sonuna öğrenmek istediğiniz uygulamanın adını koymanız yeterlidir. cheat.sh/ls adresine tarayıcınızdan da ulaşabilirsiniz.

$ curl cheat.sh/

# Displays everything in the target directory
ls path/to/the/target/directory

# Displays everything including hidden files
ls -a

# Displays all files, along with the size (with unit suffixes) and timestamp
ls -lh 

# Display files, sorted by size
ls -S

# Display directories only
ls -d */

# Display directories only, include hidden
ls -d .*/ */

Nasıl kullanayım?

Bu noktaya kadar aslında öğrenmeniz gereken her şeyi öğrendiniz. /usr/bin ve /usr/local/bin klasörleri altındaki çoğu uygulamayı bu yöntemle istediğiniz amaçlar için kullanabilirsiniz.

Örneğin ben sunucumdaki anlık bağlantı sayısını görüntülemek için aşağıdaki gibi bir kod inşa edebilirim:

curl -s http://sunucu_ip/nginx_status|head -n 1|sed -e 's/Active connections: //g'

curl ile sunucumdan anlık veriyi çekiyorum, bana detaylı bir veri çıkartıyor.

Active connections: 300
server accepts handled requests
 1544990299 1544990299 1308915160
Reading: 0 Writing: 2 Waiting: 286

Bu veri içerisinden ben head uygulaması ile sadece en üstteki satıra ihtiyacımı belirtiyorum. Buradan dönen sonucu da sed adlı kelime işlemci ile Active connections: yazan kısmı temizleyip sadece sayıya ulaşabiliyorum ki, 20 snyde bir çalışıp çıktısını bilgisayarımın bir köşesinde sürekli göreceğim için elimde sadece sayı olsun.

Araştırmacılar için çok fazla potansiyel sunan unix dünyası, işlerinizi çok hızlı bir şekilde yapmanızı sağlayacaktır. Her araştırma alanı için mevcut olan bir çok unix-felsefesini benimsemiş uygulama mevcut. Örneğin Zorro adındaki uygulama fasta formatında dna verileri için biyologların anlayacağı bir işlem yapıp sonucunu metin olarak dönüyor. Temel kuralları uyguladığı için zorro ile pipelining yaparak birleştirebileceğiniz diğer programlar işlerinizi daha kolay yapabilir hale geleceksiniz.

Buna benzer uygulamaları alanınıza göre zamanla öğrenerek, işlerinizi daha kolay halledebilir hale geleceksiniz.

Alan bağımsız

Tabi alanınızdan bağımsız olarak kurcalamanızı önereceğim bazı, her unix türevinde bulunan uygulamalar mevcut. Her uygulamada man için hazırlanmış dökümanlar olmayabiliyor. Ancak her uygulama -h parametresi ile çalıştırıldığında temel bir yardım dökümanı sunuyor.

cd klasör değiştirmenizi, ls dizin içeriği görüntülemenizi, pwd nerede olduğunuzu bilmenizi sağlar. mkdir,touch,cp,rm,mv,ln dosyalara ve klasörlere müdahale etmenizi sağlar. head,tail,less,more,cat dosyaların içeriklerini almanızı sağlar. curl,wget internetteki dosyalara erişmenize yardım eder.

uniq,sort,wc,diff,cmp,cut,sed metinlerle işlem yapmanızı sağlarken awk,grep ise metinler içerisinde desen aramanızı ve/veya işlem yapmanıza olanak sağlar.

/usr/bin ve /usr/local/bin klasörünüzü kurcalayarak diğer uygulamalar da ulaşabilirsiniz.

1: https://homepage.cs.uri.edu/~thenry/resources/unix_art/ch01s06.html

#unix #tr #bash #linux-101

Composer is an installer and a package management tool. So please stop writing build scripts for Composer, building anything inside your package folder.

Last few days, I try to deploy a Symfony project with Nixops to Google Cloud. I found composer2nix package after some research.

Composer2nix is a nix-expression builder. It parses composer.lock file and generates nix expressions for every composer packages independently. After that you can use generated files in your deployment file like that:

  pkgs = import <nixpkgs>{};
  my_app = import /var/www/app/source{
    inherit pkgs;
  };

Nix builds your application and system when you run nixops deploy.

But NixOps generates a hash folder and installs your package inside this stateless and readonly folder. After that, it makes relations all required packages and your project.

composer2nix generated expression works the same way, e.g. your composer.lock file if had thefidry/alice-data-fixtures package. composer2nix generates expression like that:

"theofidry/alice-data-fixtures" = {
      targetDir = "";
      src = composerEnv.buildZipPackage {
        name = "theofidry-alice-data-fixtures-79913820cf6965cd6ea204cc5882079486f8262e";
        src = fetchurl {
          url = https://api.github.com/repos/theofidry/AliceDataFixtures/zipball/79913820cf6965cd6ea204cc5882079486f8262e;
          sha256 = "108862vlq2j10x69h5i4f4vqh63rfizvkc5kl57ymssk79ajifz2";
        };
      };
    };

Nix uses this expression for fetching wanted package and version in the given URL, and it fetches only once if version not changed in composer.lock file.

So, as you have seen, there is no need for composer install. After the package installation process, we need the dumping autoload.php file. Nix makes that and runs composer install for checking everything is ok.

This roughly explains how composer2nix works and how to build your PHP project with nix.

But I faced a problem when I run nixops deploy command. Seems a package want to modify a file in vendor/ocramius/package-versions/src/PackageVersions/Versions.php.

I said at below, nix independently install packages in separated read-only folders. Ok. What can I do? I created an issue on the GitHub. Ocramius gently responded it and said it works if I disable running composer scripts with --no-scripts parameter. Ok, problem solved for now. But I have many scripts like assets:install or cache:clear

Now, I must manually clear caches all of the backends.

Someone should be saying “Why did you use this package and not another package?” Sorry guys, it is not about me, Sylius depends on these packages.

I decided to write this blog. Forget the Nix. It is not only about nix deployment.

I want to ask some questions to PHP package developers.

Why you are building something after package install inside the package folder. Composer not for that.

It is not only about composer scripts. Why do you modify files inside your package folder? Why vendor/<package> is not stateless?

Please don't do that. Don't touch your package folder after install.

ps: if you curios about our conversation with @ocramius about this situation, you can read from github issue

#composer #nix #php #symfony #sylius #en #nixops #composer2nix

Nixos is a Linux distro working in nix ecosystem.

NixOS is a GNU/Linux distribution that aims to improve the state of the art in system configuration management.

You need to create an instance with the configuration at the below:

  • doesn't matter which server.
  • doesn't matter which location.
  • in the server type option, select iso library and find Nixos 18.x nixos.18.x)
  • doesn't matter server size but at least we need 1GiB ram.
  • doesn't matter all of the other options.

After you deploy the server, you wait until complete server initialization.

Go to the products page and click your server name. You should see view console icon right top of the server management page. Click it and connect the terminal.

Possibly you would face some keyboard layout problems after connecting the terminal from browser. Don't get stuck that problem. We need only copy/paste initial configuration.

Vultr machines have the legacy boot option. Firstly we need to create disk partitions.

We need to know the device name for creating a partition. You can find run fdisk -l command. My device name is /dev/vda

Create an MBR partition table.

parted /dev/vda -- mklabel msdos

Add root partition

parted /dev/vda -- mkpart primary 1MiB -8GiB

And, add a swap partition

parted /dev/sda -- mkpart primary linux-swap -8GiB 100%

After that, you need to make formatting configuration.

For initializing ext4 format for the root partition.

mkfs.ext4 -L nixos /dev/vda1

For creating swap partition run mkswap.

mkswap -L swap /dev/vda2

Before installation, you need to make some little configurations. Mounting nix disk and activation swap area.

Mount nixos iso to /mnt folder.

mount /dev/disk/by-label/nixos /mnt

Activate swap area.

swapon /dev/vda2

And now we can generate the initial config.

nixos-generate-config --root /mnt

This command generates all initial disk and device configuration for you.

After creating the initial configuration completed, you need to change a few configurations. At first, you need to set boot.loader.grub.device option.

Open /mnt/etc/nixos/configuration.nix file with your favorite editor vim or nano.

Find that option and set as boot.loader.grub.device = "/dev/vda"; and enable the grub with this option boot.loader.grub.enable = true;

At the last, you need to enable OpenSSH service for connecting to your server with ssh after installation. And you need to add firewall access to 22 port.

For that, you can add that options your configuration file.

services.openssh.enable = true;
services.openssh.permitRootLogin = "yes";
networking.firewall.allowedTCPPorts=[ 22 ];

Ok. Now you can save and exit the file, and install your Nixos.

nixos-install

It asks to you for root password after you run command.

If everything went well, you should remove installation media from machine and reboot. Go to your Vultr server manage page and remove iso from settings->custom iso section. The server automatically rebooted after that.

Congrats. You can now connect your Nixos server over ssh.

#nix #nixos #vultr #howto #en

I didn't know it is possible to enable vim mode, in bash before. I learned today and this feature is awesome.

You can enable vim mode in the bash with only change a parameter in your .bashrc file, like that.

set -o vi

That's it. You can use bash with vim strokes.

#tips #vim #en #bash

You can get file path in vim with % (percent) symbol. Sometimes you need to run a command with the current file path, for example git add filepath or sh filepath.

You can add the current file to git with this command in vim:

:!git add %

or you can run any file with this command:

:!%:p

For example, you write a bash script and saved it. But you don't want to close vim or you don't want to go to another terminal screen. Just you need to write :!%:p and vim run the file for you.

#tips #en #vim #git

When you develop an API client with PHP, you would need data mapper for mapping data from API to an object.

For example, you have requested an API endpoint and you get a response like that:

{
  "user": {
    "username": "delirehberi",
    "bio": "carpenter"
  }
}

And you have a User class

<?php
class User{ 
    protected $username; 
    protected $fullname; 
    protected $bio;
      /**
     * @return mixed
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * @param mixed $username
     *
     * @return User
     */
    public function setUsername($username)
    {
        $this->username = $username;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getFullname()
    {
        return $this->fullname;
    }

    /**
     * @param mixed $fullname
     *
     * @return User
     */
    public function setFullname($fullname)
    {
        $this->fullname = $fullname;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getBio()
    {
        return $this->bio;
    }

    /**
     * @param mixed $bio
     *
     * @return User
     */
    public function setBio($bio)
    {
        $this->bio = $bio;

        return $this;
    }
}

You need to map JSON response to the PHP object. But how?

You will need to know how to use ReflectionClass, PropertyAccess, AnnotationReader.

How do you map class properties to API response fields and returns an object?

At first, you need to decode JSON string to PHP array or object.

$result = json_decode($response, true);

After that, create a Reflection class;

$reflectionObj = new \ReflectionClass(User::class);

Now you can access all properties

$properties = $reflectionObj->getProperties();

You don't need to know your User Class has which properties anymore.

Now, we need PropertyAccessor for manipulating our User object.

$propertyAccessor = PropertyAccess::createPropertyAccessor();

How can manipulate an object property with PropertyAccess object?

$propertyAccessor->setValue(
                    $userObject,
                    $property->getName(), //eg: username
                    $value //eg: emre
                );

OK, we know how to access the property of an object and how to manipulate another object properties.

Now we can start writing our data mapper.

Create an annotation class to configure properties to json values.

use Doctrine\Common\Annotations\Annotation;

/**
 * Class DataMapper.
 *
 * @Annotation
 * @Annotation\Target({"PROPERTY"})
 */
class DataMapper
{
    public $json_field;
}

We will use this object to define a JSON field equal to an object property. We can update our User class property annotations like that:

 /**
     * @var
     * @DataMapper(json_field="username")
     */
    protected $username;
    /**
     * @var
     * @DataMapper(json_field="full_name")
     */
    protected $fullname;
    /**
     * @var
     * @DataMapper(json_field="bio")
     */
    protected $bio;

note: don't forget to add DataMapper class to the header.

We are ready for writing data mapping logic.

  • Create an annotation reader object
  • Create property accessor
  • Create a new empty object (eg: User)
  • Create a reflection object for reach properties
  • Get object properties from reflection object
  • Foreach to properties
    • read property annotation for DataMapper annotation
    • get json_field value from annotation
    • access data from JSON with json_field value
    • set property of a new object with data
  • return new filled object :)
$reader = new AnnotationReader();
$propertyAccessor = PropertyAccess::createPropertyAccessor();
$user = new User();
$reflectionObj = new \ReflectionClass(User::class);
$properties = $reflectionObj->getProperties();
foreach ($properties as $key => $property) {
  $propertyAnnotation = $reader->getPropertyAnnotation($property, DataMapper::class);
  $json_field = $propertyAnnotation->json_field;
  if(!$json_field) continue;
  $value = $result[$json_field];
  $propertyAccessor->setValue(
                    $user,
                    $property->getName(),
                    $value
                );
}

var_dump($user);

Congrats, you can write as a function and use in your project.

#php #reflection #datamapper #annotation #annotationreader #doctrine #symfony

You can run the same command in all active Tmux panes at the same time.

You need to activate command mode in Tmux with Ctrl+B keys and update synchronize-panes setting to on.

:setw synchronize-panes on

To disable it, set as off.

:setw synchronize-panes off

You can toggle synchronize-panes setting without use on-off parameters.

:setw synchronize-panes

#tmux #tips