27 Temmuz 2020 Pazartesi

bash wildcard expansion

Giriş
Wildcard expansion komut çalıştırılmadan önce olur.

Örnek
Elimizde şöyle bir dizin olsun
~ $ ls
Documents
Desktop
Downloads
Şöyle yaparız
~ $ cd *ments
~/Documents $
Açıklaması şöyle
That's because bash can do the substitutions before the command ever gets to cd.
Ancak bazen komutlar expansion'a sonucundaki girdiyi beğenmezler.
~ $ cd *s
bash: cd: too many arguments

24 Temmuz 2020 Cuma

bash parameter expansion - Genellikle String İşlemleri İçindir

Giriş
Parameter expansion çok fazla farklı söz dizimine/forma sahip. Bu yüzden bence karışık bir konu. Bazı temel özellikler şöyle

Temel Kullanım

1. Değişkenin Değerine Erişmek
Bir değişkenin değerine erişmek istediğimizde parameter expansion yapmak gerekir. Bu durumda $foo şeklinde kullanırız. Yani dolar işaretinden sonra değişken ismi gelir. 

Bazen değişkene bitişik olarak başka karakterler de bulunur. Bu durumda değişken ismini süslü parantezler içine almak gerekir. ${foo}abc şeklide kullanırız

2. Değişkene Varsayılan Değer Atamak - Default Expansion
Değişkene değer atanmamışsa varsayılan bir değer kullanmak isteyebiliriz. Açıklaması şöyle
One useful form of parameter expansion is to use a default value for a variable if it is not set. This is done with the syntax: ${VAR:-DFLT}.
Örnek
Şöyle yaparız
TEST_MODE=${TEST_MODE:-0}

3. Değişkenini Uzunluğuna Erişmek
Açıklaması şöyle
The final form of parameter expansion I want to mention is one which simply expands to the length of the variable's value, its form is ${#VAR}.
Örnek
Şöyle yaparız
str=abcdef
echo ${#str}
Çıktı olarak 6 alırız

Gelişmiş Kullanım

1. Replace a Substring veya String Substitution
Açıklaması şöyle
Another useful form of parameter expansion is to expand a variable and do string substitution on the value using the form ${VAR/search/replace}
Örnek
Şöyle yaparız. var1 değişkeni içindeki placeholder var2 ile yer değişiyor
var1='<tr>
    <th>unique_placeholder_var2</th>
  </tr>'
var2=test
echo "${var1/unique_placeholder_var2/"$var2"}"

Örnek
Şöyle yaparız
files=(*)
echo "${files[@]/#/--hidden-import=}"
Açıklaması şöyle. Eşleşmenin başına "--hidden-import="  eklemesi yapar.
Here the # in ${var/#match/replacement} makes it replace the (zero-length) matching string only at the beginning of the variable. Also note the usage of files[@] to get all elements of the array instead of just the first one.
Çıktı olarak şunu alırız
--hidden-import=cpu_mon --hidden-import==disk_mon --hidden-import==mem_mon
2. Remove Suffix - % veya %% Kullanılır
Açıklaması şöyle. Tek % karakteri varsa en kısa eşleşme silinir, çift % karakteri varsa en uzun eşleşme silinir.
The form ${VAR%pattern} removes a matching suffix (single percent for the shortest suffix, double for the longest). 
Remove Suffix ve Remove Prefix ile ilgili hatırlatıcı bir not şöyle
Note: if you have trouble remembering which is which of these two syntaxes, the "#" is to the left of the "%" key on your keyboard, just as prefixes come before suffixes. Also note that these are glob patterns not regular expressions.
Örnek
Şöyle yaparız. TLC_2017.csv isimli dosyayı TLC_2017_prepped.csv haline getirir
for file in TLC*.csv; do
    cut -d, -f2- "${file}" > "${file%.*}_prepped.csv"
done
Açıklaması şöyle
${file%.*} removes everything after the last dot of $file. If you want to remove everything after the first dot, then you would use %%.

Likewise, ${file#*.} and ${file##*.} remove everything before the first/last dot.

3. Remove Prefix - 
# veya ## Kullanılır
Açıklaması şöyle. Tek hash karakteri varsa en kısa eşleşme silinir, çift hash karakteri varsa en uzun eşleşme silinir.
The form ${VAR#pattern} removes any prefix from the expanded value that matches the pattern. The removed prefix is the shortest matching prefix, if you use double pound-signs/hash-marks the longest matching prefix is removed.
Örnek
Şöyle yaparız. İlk karakteri siler
$ line=abc; echo "${line#?}"
bc
Açıklaması şöyle
More generally, ${variablename#word} removes word from the beginning of the contents of variablename. This is called prefix removal. word is treated as a glob which means that ? matches any single character.
Örnek
Şöyle yaparız. proj_env_repo ile başlayan bir sürü değişken bulunur. Bu değişkenlerin isminden proj_env_repo çıkarılır. Böylece TF_ENV_db_username değişkeni username değeri ile export edilir.
proj_env_repo_db_username=username
proj_env_repo_db_host=host
proj_env_repo_db_port=port

for variable in "${!proj_env_repo@}"; do
    export "TF_ENV${variable#proj_env_repo}"="${!variable}"
done

4. Extract Substring
Açıklaması şöyle. Offset olarak eksi sayılar da kullanılabilir. 
Another expansion that exists is to extract substrings from the expanded value using the form ${VAR:offset:length}. This works in the expected form: offsets start at zero, if you don't specify a length it goes to the end of the string. 
Örnek
Bir sayının ilk karakterine erişmek için şöyle yaparız.
$ var=901.32.02
$ first_char="${var:0:1}"
$ echo "${first_char}"
9
Örnek
Eksi sayı verirsek sondan itibaren ileriye doğru sayar. Eksi sayıları echo ${str:-3:2} şeklinde yazamıyoruz çünkü "Default Expansion" ile karışıyor. Bu yüzden eksi sayıları parantez içine almak lazım. Şöyle yaparız. Çıktı olarak "fg" alırız
str=abcdefgh
echo ${str:$((-3)):2}
Açıklaması şöyle
The "$((...))" causes bash to treat the value as an arithmetic expansion (ie a number)

5. Convert Uppercase to Lowercase veya tersi
Örnek
Şöyle yaparız.
$ str="HELLO"
$ printf '%s\n' "${str,,[HEO]}"
heLLo

top komutu

Giriş
İşlemcileri izlemek için gnome-system-monitor uygulamasının Resources sekmesi benim tercihim.

top uygulaması q tuşuna basında sonlanınca ekranı temizlemiyor. Temizlemesi için şöyle yaparız.
top && clear
Çıktı
1. En üstte sistemle ilgili özet bilgiler var
2. Altında ise sütunlar var

Tuşlar
i tuşu
Açıklaması şöyle
top is an interactive program, for instance you can type i to toggle showing idle processes.

1. Özet Bilgiler
1.1 Tasks Satırı
1.2 Cpu(s) Satırı
%us %sy %ni %id %wa %hi %si %st ile biten değerler var

%us
Toplam işlemci kullanımını gösterir. Eğer %100 ise sistem çok dolu demektir. "Chaos Engineering" için bu yük testi yapılabilir.

%ni ile biten değer "Nice CPU Time" anlamına gelir
Açıklaması şöyle
‘nice CPU time’ is the amount of time a CPU spends in running low priority processes (whose nice values are greater than 0). 

%wa ile biten değer "Waiting CPU Time" anlamına gelir.
Açıklaması şöyle
Waiting CPU time indicates the amount of time the CPU spends waiting for disk I/O or network I/O operations to complete. A high waiting time indicates that the CPU is *stranded* because of the I/O operations on that device. For optimal performance, one should aim to keep the I/O waiting CPU time as low as possible. If waiting time is > 10%, then it is worth investigating it.
%si ile biten değer "Software Interrupt Time" anlamına gelir
Açıklaması şöyle
Software interrupts can be triggered because of the following events:

- When software run into exceptional conditions such as a divide by zero or accessing unavailable memory.
- When a special instruction in the application code causes an interrupt when the processor executes it.
- Some hardware interrupts might take a long time to complete. In such scenarios, hardware interrupts can be deferred to execute at a later point of time through software interrupts. Software interrupts can be scheduled to run independently or on any CPU in the device or even run concurrently. On the other hand, these flexibilities don’t exist in hardware interrupts.

The amount of time the CPU spends in processing these software interrupt signals is called ‘Software interrupt time’. 
1.3 Mem Satırı
1.4 Swap Satırı

2. Sütunlar
USER Sütunu
Uygulamayı çalıştıran kullanıcı 8 karakter uzunluğunda. Açıklaması şöyle.
The default width for the USER column is 8 characters, and the column doesn’t scale with its contents. The width can be adjusted with X while top is running.
PR ve NI Sütunu
Priority ve Nice değerlerini gösterir. NI sütunu nice komutu ile atanabilir.
Örnek
Şöyle yaparız. Burada 3239 numaralı process'in thread'lerini görüyoruz. Java thread'i 20 PR (priority) değerine sahip. HighPriority ve LowPriority ismine sahip thread'ler ise 17 ve 23 PR (priority) deperlerine sahipler. Dolayısıyla NI (nice) değerleri de ona göre
$ top -p 3239
|  PID | PR | NI | VIRT    |   RES | %MEM | COMMAND         |
|------+----+----+---------+-------+------+-----------------|
| 3239 | 20 |  0 | 10.686g | 33996 |  0.1 | java            |
| 3256 | 17 | -3 | 10.686g | 33996 |  0.1 | HighPriority    |
| 3257 | 23 |  3 | 10.686g | 33996 |  0.1 | LowPriority     |
RES Sütunu
Açıklaması şöyle. Kullanılan RAM miktarını gösterir.
The RES column is physical memory. The VIRT column shows all the virtual memory used by the process. According to man top, that includes all code, data, and shared libraries plus pages that have been swapped out and pages that have been mapped but not used.
S Sütunu
S sütununda - Status sütunu anlamına gelir - bazı harfler görünür. Bir harf Z ise Zombie anlamına gelir. Harfle şöyle
Process status is reported with a single character:

R — RUNNING/RUNNABLE
S — INTERRUPTABLE_SLEEP
D — UNINTERRUPTABLE_SLEEP
T — STOPPED
Z — ZOMBIE
3. Seçenekler

- b seçeneği
batch mode seçeneği. Çıktıyı başka programa gönderir. Açıklaması şöyle.
The -b argument makes top run in batch mode – the information is gathered, displayed, and then dumped to stdout as opposed to running in an interactive mode and refreshing the data displayed.

With the -b option, the user must tell top how many times to run, this is done with the -n argument and a final argument with how many times to run.
Örnek
Şöyle yaparız.
top -b | awk '/dockerd/ {print strftime("%Y-%m-%d-%H:%M:%S"), $0}'
Çıktı olarak şunu alırız.
2017-05-11-18:54:18  2569 root 20 0  624m  41m  28m S  0.0  4.2   0:07.32 dockerd
2017-05-11-18:54:21  2569 root 20 0  624m  41m  28m S  0.0  4.2   0:07.32 dockerd
2017-05-11-18:54:24  2569 root 20 0  624m  41m  28m S  0.0  4.2   0:07.32 dockerd
Örnek
Şöyle yaparız.
watch top -b
-H seçeneği
thread'leri göster seçeneği. Açıklaması şöyle.
The -H argument instructs top to display each individual thread. Normally top summarizes all threads under their parent process.
Örnek
Şöyle yaparız.
top -H -b -n 1
Örnek
Bir process'in thread'lerini izlemek istersek kullanabiliriz. Şöyle yaparız.
top -H -p <pid>
Eğer -H seçeneği desteklenmiyorsa -p ile process'i görüntüledikten sonra klavyede H tuşuna basarak aynı sonucu elde edebiliriz.

-p seçeneği - pid verilir
Örnek
Şöyle yaparız
top -p "$(pgrep gvfs | paste -s -d ',')"


22 Temmuz 2020 Çarşamba

Systemd İçin Service Dosyası

Giriş
Bu dosya temel olarak [Unit], [Service], [Install] başlıklarından oluşur. Bu dosyanın yolu şöyledir.
/etc/systemd/system/foo.service
Kullanım
Örnek
İsmi xrandr olan bir servis yaratmak isteyelim. İzlenecek adımlar şöyle. İkinci adım olan 
"systemctl enable ..." ile bilgisayar tekrar başlatılınca servis te çalışır.
- Create a /etc/systemd/system/xrandr.service file (you could specify the service name you like) - sudo chmod 664 /etc/systemd/system/xrandr.service
- sudo systemctl enable xrandr.service
- Check if it is working by sudo systemctl start xrandr.service
Örnek
Açıklaması şöyle
To make your service start automatically upon boot, run

systemctl --user enable my_example.service
If you want to start the service immediately, without rebooting, run

systemctl --user start my_example.service
If you want to stop the service, run

systemctl --user stop my_example.service
To check the status of your service, run

systemctl --user status my_example.service
Service Template
Bazı servisler bilgisayar açılırken değil, bir istek gelince çalışmak üzere (instantiated) ayarlanabilir. Buna service template deniliyor. Açıklaması şöyle.
It is possible for systemd services to take a single argument via the "service@argument.service" syntax. Such services are called "instantiated" services, while the unit definition without the argument parameter is called a "template". An example could be a dhcpcd@.service service template which takes a network interface as a parameter to form an instantiated service. Within the service file, this parameter or "instance name" can be accessed with %-specifiers.
Açıklaması şöyle.
Some applications, like ssh have a unit file that ends with @, like ssh.service and ssh@.service
1. [Unit] Başlığı
Description, ConditionPathExists, After alanları olabilir.
After Olarak network.target ve network-online.target Değerleri
Açıklaması şöyle. Servisimiz network başladıktan sonra çalışsın isteyebiliriz.
network.target has very little meaning during start-up.

network-online.target is a target that actively waits until the nework is "up"
Şöyle yaparız
[Unit]
Description=Streamer
After=multi-user.target sound.target network.target

[Service]
ExecStart=/home/pi/run.sh
KillMode=control-group
Restart=on-failure
TimeoutSec=1

[Install]
WantedBy=multi-user.target
Alias=streaming.service
2. [Service] Başlığı - Çalıştırılacak Uygulama Burada Tanımlanır
Type, RemainAfterExit, ExecStart, ExecStartPre, ExecStartPost, ExecStop alanları olabilir. EnvironmentFile ile dosyadan değerler okunabilir

Örnek
Şöyle yaparız. EnvironmentFile  dosyasında PORT değeri okunur. Bu değere ${PORT} ile erişilir.
[Service]
Type=simple
EnvironmentFile=/etc/my-service/my-service-systemd.cfg
ExecStart=/usr/local/bin/my-service -port=-port=${PORT}
ExecStop=/bin/kill -15 $MAINPID

Type=simple Nedir
Type alanı oneshot,forking,notify gibi değerler alabilir. 

Açıklaması şöyle
Service management subsystems launch service processes in dæmon context already. Those processes do not need to "dæmonize". ... They already have the environment values, and open file descriptors, appropriate to dæmon context, and the several things done by "dæmonization" in fact thwart some of the conventional things that are regularly done with dæmons (e.g. capturing their standard outputs/errors to a log) by service managers.
Açıklaması şöyle
The currently popular systemd init system does not use a shell at all when starting services, so you can define a .service and start it – the service's parent will be init itself. It also has a feature allowing temporary services to be created on-the-fly using systemd-run, with the same results.
Type = simple
Açıklaması şöyle. systemd process'in start işlemini beklemez
Type=simple (default): systemd considers the service to be started up immediately. The process must not fork. Do not use this type if other services need to be ordered on this service, unless it is socket activated.
Type=forking
Açıklaması şöyle. systemd process'in start işlemini bekler
... for type=forking jobs, indicates the process spawn directly by systemd ...
Örnek
Şöyle yaparız
[Unit]
Description=Vendor's Application 
After=network-online.target

[Service]
ExecStart=/path/to/wrapper start
ExecStop=/path/to/wrapper stop
Type=forking

[Install]
WantedBy=multi-user.target
ExecStart ile başlatılan script'in parent'ı Systemd olur. Bu script'in elle çalıştırılmadığını kontrol etmek için şöyle yaparız
if [[ $PPID -ne 1 ]]
then
  echo "Don't call me directly; instead, call 'systemctl start/stop service-name'"
  exit 1
fi >&2
Örnek - ExecStart Alanı
Servis başlarken bir tane scrip çalıştırabilmeyi sağlar. Şöyle yaparız
[Unit]
After=multi-user.target

[Service]
User=your_user
ExecStart=/home/your_user/scripts/xrandr.sh

[Install]
WantedBy=default.target
Örnek
Şöyle yaparız
[Unit]
Description=[My example task]

[Service]
Type=simple
StandardOutput=journal
ExecStart=/usr/local/bin/mytask

[Install]
WantedBy=default.target
Örnek - ExecStart + WorkingDirectory
WorkingDirectory vermek için şöyle yaparız.
[Unit]
Description=My Smtp Service
After=multi-user.target

[Service]
Type=idle
WorkingDirectory=<my path script dir>
ExecStart=/usr/bin/python smtp.py

[Install]
WantedBy=multi-user.target
Örnek - ExecStop
Şöyle yaparız. Bu servis 1 saat uyuduktan sonra dururken iptables komutunu çalıştırır. Servisimiz başlamadan önce ExecStartPre ile iptables servisinin başlaması sağlanır.
[Unit]
Description=unblock internet 1 hour
[Service]
Type=simple
ExecStartPre=/usr/sbin/iptables ...
ExecStart=/usr/bin/sleep 3600
ExecStop=/usr/bin/iptables ...
3. [Install] Başlığı
WantedBy alanı olabilir.
Örnek
Şöyle yaparız.
[Unit]
Description=Copy user mac_override.link
ConditionPathExists=/boot/mac_override.link
After=local-fs.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/mv /boot/mac_override.link /etc/systemd/network/00-default.link
ExecStartPost=/sbin/reboot

[Install]
WantedBy=multi-user.target
Örnek
tomcat için şöyle yaparız.
[Unit]
Description=Apache Tomcat Web Application Container
After=syslog.target network.target

[Service]
Type=forking

Environment=JAVA_HOME=/usr/lib/jvm/java-8-oracle/jre
Environment=CATALINA_PID=/opt/tomcat9/temp/tomcat.pid
Environment=CATALINA_HOME=/opt/tomcat9
Environment=CATALINA_BASE=/opt/tomcat9
Environment='CATALINA_OPTS=-Xms512M -Xmx4096M -server -XX:+UseParallelGC'
Environment='JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom'
Environment=JPDA_ADDRESS=1144

ExecStart=/opt/tomcat9/bin/catalina.sh jpda start
ExecStop=/bin/kill -15 $MAINPID

User=tomcat
Group=tomcat
UMask=0007
RestartSec=10
Restart=always

[Install]
WantedBy=multi-user.target
Örnek
Environment vermek için şöyle yaparız.
[Unit]
Description=WSO2EI

After=syslog.target
After=network.target

[Service]
Type=simple
WorkingDirectory=/usr/lib/wso2/wso2ei/6.4.0
User=root
Group=nogroup
Environment=JAVA_HOME=/usr/lib/wso2/wso2ei/6.4.0/jdk/jdk1.8.0_192
Environment=CARBON_HOME=/usr/lib/wso2/wso2ei/6.4.0

StandardOutput=syslog
StandardError=syslog

ExecStart=/usr/lib/wso2/wso2ei/6.4.0/bin/integrator.sh
ExecStop=/usr/lib/wso2/wso2ei/6.4.0/integrator.sh stop

#TimeoutSec=130

[Install]
WantedBy=multi-user.target
Örnek
Sadece sshd ve networkd servisini çalıştırmak için şöyle yaparız.
[Unit]
Description=Maintenance Mode with Networking and SSH
Requires=maintenance.target systemd-networkd.service sshd.service
After=maintenance.target systemd-networkd.service sshd.service
AllowIsolate=yes
Restart Seçeneği
Açıklaması şöyle
Restart= Configures whether the service shall be restarted when the service process exits, is killed, or a timeout is reached....
Şöyle yaparız
Restart=always
RestartSec=0
4 [Slice] Başlığı
Şöyle yaparız.
$ systemctl --user cat mozilla.slice 
# /home/anthony/.config/systemd/user/mozilla.slice
[Unit]
Description=Slice for Mozilla apps
Before=slices.target

[Slice]
MemoryAccounting=yes
MemoryHigh=5G
MemoryMax=6G

$ systemd-run --user --slice mozilla.slice --scope -- /usr/bin/firefox &
$ systemd-run --user --slice mozilla.slice --scope -- /usr/bin/thunderbird &