Category Archives: Linux

Categorie dedicata articolelor tehnice ce tin de distributiile Linux in general.

“Process locking” folosind PHP / *nix

< ?php
$fh = fopen(dirname(__FILE__).DIRECTORY_SEPARATOR.'.lock', 'w+');
 
if (flock($fh, LOCK_EX | LOCK_NB) === TRUE)
{
	// Functional code
	$exit = FALSE;
	while($exit === FALSE)
	{
		$exit = TRUE;
		sleep(10);
	}
	// End Functional code
	flock($fh, LOCK_UN);
}
else
{
	echo "This script is locked by another process.\n";
}
 
fclose($fh);

MySQL Backup peste SSH

Update (1 Martie 2011):

  • Suport pentru a specifica un MySQL host. E musai să fie definit minim cu “localhost” pentru o conexiune locală. Va folosi UNIX socket. Pentru TCP socket, se folosește 127.0.0.1 ca adresă.
  • Suport pentru compresie la nivel de protocol SSH. Mă gândeam la asta, dar am activat-o doar pentru MySQL – chestie destul de inutilă pentru o conexiune locală prin UNIX socket. Acum, cu suport pentru host extern, își are rostul.
  • Schimbat criptarea în blowfish-cbc ce este semnificativ mai rapidă pentru SSH.

Backup-ul – un rău necesar. Existența unui server cu skip-networking complică problema. Dar nu o face imposibilă. SSH știe să returneze chestii peste STDOUT. Iar un script pus în cron face ca această pacoste să intre în categoria “set it and forget it”.

Iar dacă tot am vorbit de un script, acesta este:

#!/bin/bash
 
# EDIT
MY_USER=""
MY_PASS=""
MY_HOST="localhost"
SSH_USER=""
SSH_HOST=""
SSH_PORT=""
# END EDIT
 
CDIR=$(dirname $0)
PKEY=$CDIR/private-key.pem
DUMP=$CDIR/dump
DATE=$(date +%F+%H-%M-%S)
 
if [ ! -f $PKEY ]
then
        echo "Error: The SSH private key file is missing!"
        exit 1
fi
 
if [ ! -d $DUMP ]
then
        mkdir $DUMP
fi
 
echo "Fetching the databases ..."
database=($(ssh -C -c blowfish-cbc -i $PKEY -p $SSH_PORT $SSH_USER@$SSH_HOST mysql -C -h$MY_HOST -u$MY_USER -p$MY_PASS -e '"SHOW DATABASES;"'))
count=${#database[@]}
for ((i=1; i<count ; i++))
do
        if [ "${database[$i]}" != "mysql" -a "${database[$i]}" != "information_schema"  ]
        then
                echo "Dumping ${database[$i]} ..."
                ssh -C -c blowfish-cbc -i $PKEY -p $SSH_PORT $SSH_USER@$SSH_HOST mysqldump -v -C -h$MY_HOST -u$MY_USER -p$MY_PASS -x -B ${database[$i]} | nice -n 19 pbzip2 -c > $DUMP/${database[$i]}-$DATE.sql.bz2
        fi
done
 
</count>

Are 5 opțiuni de configurare, destul de evidente. Caută private-key.pem în directorul în care se află – unde private-key.pem este cheia ce face posibilă comunicarea peste SSH fără a folosi autentificare cu parolă. Iar din moment ce se folosește rețeaua, atât mysql cât și mysqldump folosesc protocol compression (flag-ul -C). Dependințele sunt evidente la o primă citire. Nu este cel mai eficient mod de a face backup (rețea, spațiu), dar este simplu de implementat iar câteodată aceasta contează. Ignoră bazele de date mysql și information_schema. A se ignora ultimul tag a-la HTML din blocul de cod de mai sus. GeSHi face fițe.

Parole aleatoare în Linux, “extended ASCII”

Deși în teorie problema din titlu este una rezolvată, în practică de multe ori mi-am dorit o parolă de o complexitate mai mare față de ce-mi oferă majoritatea uneltelor ce nu ies din standard ASCII. Prin metoda subsemnatului, se ia următoarea funcție și se trântește în .bashrc:

function urandompass()
{
	cat /dev/urandom | tr -dc '[\41-\176\241-\254\256-\376]' | fold -w $1 | head -n 1
}

Apelul este cretin de simplu: urandompass 12 va genera o parolă de 12 caractere. Sau cheie, am zis-o și pe asta. Funcția poate fi folosită pentru a genera chei pentru un “block cipher”.

Cu toate acestea, pentru cei cu terminalul setat pe UTF-8, caracterele dincolo de range-ul celui de-al 7-lea bit (aka cele ce intră în extended ASCII) nu vor fi printate corect. Teoria spune faptul că UTF-8 este compatibil doar cu setul ASCII, ăla standard. În prealabil este nevoie să se seteze terminalul pe un char encoding single-byte ce implementează vreo formă de extended ASCII gen ISO-8859-x, unde x = 1 este Western, x = 2 = Central European, etc. Personal prefer Western. Pentru cei cu Gnome Terminal, “Terminal » Set Character Encoding » Add or Remove …” dacă e pentru prima dată, dacă nu, atunci ar trebui să poată fi ales din meniu un encoding diferit de cel implicit. Buba este faptul că Gnome Terminal are memorie destul de proastă deci va da reset la UTF-8 dacă terminalul este închis sau se execută reset, deci operația trebuie repetată înainte de a genera orice parolă / cheie.

Acum urmează partea pentru obsedații de detalii aka cei după chipul și asemănarea subsemnatului. “Limitarea” la extended ASCII, ce oricum oferă o complexitate mai bună decât majoritatea generatoarelor, provine de fapt din tr. Un info coreutils ‘tr invocation’ în shell specifică destul de clar: “Currently `tr’ fully supports only single-byte characters.”, deci suportă multi-byte din jumătatea lui cinci. Pentru amatorii de detalii, acele range-uri din funcția mea au fost documentate, oarecum, în prealabil.

În DEC:

33-126
161-172
174-254

În OCT:

41-176
241-254
256-376

Evident, cu ochiul liber se poate vedea că tr primește octal, precum zice manualul. Pentru a le determina am încercat cu encoding ISO-8859-1 și ISO-8859-2 o aplicație ce printează tot range-ul single-byte (mă rog, fără ultimul caracter).

Pentru PHP-iști:

for ($i = 0; $i < 256; $i++)
{
	echo $i.': '.chr($i)."\n";
}

Iar pentru snobii cu C, avem alternativă 😀 :

#include 
 
int main()
{
        for (int i = 0; i < 256; i++)
        {
                printf("%d: %c\n", i, i);
        }
        return 0;
}

gcc -std=c99 -o chars chars.c

Inițial m-am inspirtat dintr-o versiune *sh de pe linuxquestions.org, dar arată cretin, nu dau paste la așa ceva. Mă cam strânge octalul de dinți. O versiune rescrisă pentru DEC junkies:

#!/bin/bash
 
chr()
{
	printf \\$(printf '%03o' $1)
}
 
i=0
while [ $i -lt 256 ]; do
	echo "$i: `chr $i`"
	let "i++"
done

Pentru cei ce preferă alte encoding-uri single-byte, dacă range-urile de mai sus nu sunt potrivite, atunci se poate rula oricând vreo aplicație de mai sus pentru a face un test de char printing.

Pentru cei ce nu s-au născut cu “DEC to OCT converter” în cap, așa ca subsemnatul, Calculator din Gnome (gcalctool) are și un mod Programming (Ctrl+P).

Scanarea disk-urilor sub Linux

O să intru puţin şi în acest subiect. Nu, nu mă refer la chestii de filesystem gen fsck plus familia de prieteni, LVM şi alte avioane, ci la chestii dincolo de date, mai apropiate de fier. Nu oricine deţine un motan idiot ce să folosească un minitower pe post de suprafaţă de frânare, şi să-l dărâme, dar problemele pot apărea şi în stare naturală, “fat free, batteries not included”. Chiar dacă maşina respectivă în timpul impactului era oprita (fapt ce a oferit oportunitatea de a fi dărâmată), cele două disk-uri aveau capetele parcate, conform specificaţiilor suportă acceleraţii de până la 300G dacă sunt staţionate, wonk, wonk, wonk. Ideea simplă este faptul ca pentru a fi sigur de stabilitatea soluţiei, sunt necesare nişte măsuri ulterioare producerii unui eveniment nedorit.

a) S.M.A.R.T.

S.M.A.R.T.-ul (Self-Monitoring, Analysis, and Reporting Technology) acesta deştept, pe lângă faptul de a furniza o târlă “geeky parameters” ştie să ruleze şi nişte teste automate la nivel de disk, a căror rezultate se salvează în log-ul propriu, fapt ce duce această tehnologie dincolo de graniţele sistemului de operare.

O să presupun că disk-ul în cauză este /dev/sda, eventual faptul că scanarea se face dintr-un live edition pentru a elimina anumite probleme potenţiale. Instalarea sub Debian & Friends se face prin pachetul smartmontools. Utilitarul interesant este smartctl.

smartctl -i /dev/sda

Comanda va returna informaţiile de bază despre disk, dintre care cele mai importante pentru a continua sunt ultimele două:

SMART support is: Available – device has SMART capability.
SMART support is: Enabled

Dacă e “Available” şi e “Disabled”, atunci se poate activa şi fără reboot pentru a meşteri prin BIOS. Dacă e “Unavailable”, atunci poţi să arunci rabla de HDD de pe bloc sau intru într-o zonă a disk-urilor ce mă depăşeşte.

smartctl -s on /dev/sda

Această comandă va activa S.M.A.R.T. dacă există. Dacă nu, citeşte paragraful anterior. Dacă da, lectură plăcută în continuare.

smartctl -a /dev/sda

Va da lista aceea de “geeky parameters” despre starea HDD-ului.

SMART overall-health self-assessment test result: PASSED

Ar fi bine să indice acel PASSED. Dacă nu, ar fi cazul să îţi salvezi datele şi să înlocuieşti echipamentul. De regulă ar trebui să fie acompaniate erorile şi de ceva descrieri. In principiu informaţiile cu flag-ul “Pre-fail” ar trebui să fie OK.

Dacă totul este OK, atunci se poate trece fără grijă la auto-teste. Ca idee există vreo 3, două rapide şi unul lent. Le recomand pe cele rapide să fie primele:

smartctl -t short /dev/sda

După ce trece timpul alocat testului se va rula:

smartctl -t conveyance /dev/sda

Atenţie, testele nu pot fi rulate în paralel sau puse în coadă. Execuţia unui nou test o va anula pe cea anterioară.

Se poate trage cu ochiul la progres prin:

smartctl -c /dev/sda

Cu toate acestea, nu are vreo formă de “progress bar”, doar un procent rămas pâna la terminare, actualizat din 10% în 10%.

Lista rezultatelor stocate în log-ul HDD-ului se poate afla prin:

smartctl -l selftest /dev/sda

Ca regulă generală, log-ul stochează ultimele 20 teste. Nu îţi pierde vremea (precum subsemnatul) căutând o metodă de resetare a log-ului. O fi existând vreo soluţie, nu am dat de ea în smartctl.

=== START OF READ SMART DATA SECTION ===
SMART Self-test log structure revision number 1
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 1 Extended offline Completed without error 00% 19368 –
# 2 Conveyance offline Completed without error 00% 19366 –
# 3 Short offline Completed without error 00% 19366 –

Cam aşa arată la mine după cele 3 teste, iar acestea sunt rezultatele “ochei”. Nu am zis de ultimul, acesta durează cât căderea turnului din Pisa şi a doua venire a lui Hristos la un loc. Este direct proporţional cu dimensiunea disk-ului şi bănuiesc faptul că ţine şi de viteza acestuia. Ultimul test se rulează prin:

smartctl -t long /dev/sda

Este un moment bun să îţi faci cafeaua, dacă bei cafea, să scoţi câinele la plimbare, dacă ai vreunul, etc. O să dureze suficient de mult, în special la dimensiunile disk-urilor din zilele de astăzi.

Parametrul -c al smartctl pe lângă starea execuţiei unui test anume furnizează şi durata lor:

Short self-test routine
recommended polling time: ( 2) minutes.
Extended self-test routine
recommended polling time: ( 147) minutes.
Conveyance self-test routine
recommended polling time: ( 5) minutes.

În concluzie îţi poţi programa din timp ceva ce să umple acel gol. Din păcate numerele nu sunt precum progress bar-ul din Windows 98 unde arăta sute de ani şi termina în 5 minute sau un progress bar ce avansează dar timpul rămas creşte. Cam atâta durează testele pe bune şi pe rele. Datele de mai sus sunt de la un WD5000AAJS, adică un HDD de 500GB, 8MiB cache şi peste 19300 de ore de funcţionare. Da, are peste 2 ani de uptime, e normal din moment ce rulează în propriul server. Fratele geamăn, camarad de mirror, a murit răpus de Buleptrica, fie-i platanele uşoare. Cu această ocazie am făcut şi comemorarea soldatului căzut la datorie.

b) badblocks

badblocks este un utilitar, potenţial agresiv, menit să scormonească platanele şi să indice existenţa sau inexistenţa sectoarelor defecte. Spre exemplu eu am o mândreţe de HDD Fujitsu-Siemenes cules din notebook (ce a primit la scurt timp după achiziţionare un binemeritat upgrade la 7200 RPM). Junghiul acesta de disk corupe datele, n-are S.M.A.R.T. şi nici bad-uri. L-am scanat de câteva ori, cu mai multe utilitare, de unde concluzia că suferă de alte genuri de defecţiuni, recte electronice. Concluzia scurtă a poveştii de mai sus este faptul că badblocks nu este panaceu, identifică problemele pentru care a fost creat. Disk-urile nu trebuie să fie montate pentru a evita orice problemă, dacă au partiții. Deasemenea se recomandă prezența unei distribuții live, eventual în cazul în care aceasta nu este disponibilă, single user mode cu root montat ca read only.

badblocks -sv /dev/sda

Va rula un read only test şi arată progresul operaţiei. Durează ceva vreme, cam o oră şi ceva în cazul meu.

root@ubuntu:~# badblocks -sv /dev/sda
Checking blocks 0 to 488386583
Checking for bad blocks (read-only test): done
Pass completed, 0 bad blocks found.

Dacă vrei un test mai agresiv pentru disk, există și moduri read-write. Există doi parametri mari și lați: -n pentru read-write non-distructiv, recomandat pentru disk-uri ce au date pe ele, sau -w pentru read-write distructiv și îți poți lua gândul de la date cu -w, deci atenție. Parametrii -n și -w sunt disjuncți deci nu se vor utiliza împreună în aceeași comandă.

EOF