Հեղինակների պահոցներ՝ Անդրանիկ Վարդանեան

Անդրանիկ Վարդանեան-ի մասին

Համահիմնադիր @ իլլուրիա։ Փոխտնօրէն @ Մութ Ուժեր™։ Խոնարհ ծառայ @ Համացանց։ միշտ կարգիչի դիմաց։ հիմնականում անվնաս։

Անքուն գիշեր, անցած տարի

Բարի լոյս։

Կամ բարի ուշ գիշեր, եթէ իմ նման չես քնել։ Աւաղ, նման օրեր լինում են, երբ չենք կարողանում քնել եւ մտքերով ենք լինում։

Ես երբ անքուն եմ լինում սկսում եմ գրել։ Գրում եմ չաթով ինչ֊որ մէկին, կամ էլ մտնում եմ IRC ալիքներում եմ տուսւում (նորայրի ասած)։

Բայց այսօր որոշեցի գրել, այսօր որոշեցի խօսել քեզ հետ, վաղուց միասին չէինք խօսել։

Անցած տարին ահագին բարդ էր։ Սկզբում լաւ էր, մեզ թւում էր, որ COVID֊ը մեր վրայ այդքան էլ չի ազդելու։ Բայց մի քանի ամիս անցաւ եւ շատ բան սկսեց վատանալ։ Իհարկէ, վատ ժամանակ միշտ յայտնւում են լաւ ընկերները եւ փրկում են մեզ։ Ինձ էլ յայտնուեց մի հին, շատ լաւ ու բարի ընկեր։ Փրկեց։

Հիմա վատ չեմ, բնաւ, բայց արի մի քիչ էլ անցեալից խօսենք։

Անցած տարին հետաքրքիր էր, շատ բաներ սովորեցինք մենք մեր մասին։ Սովորեցինք ինչպէս շփուել առանց շփուելու, սովորեցինք լսել առանց խօսելու։ Դէ մի տեսակ ստիպուած, դժուար է վիդէո֊զանգի ժամանակ մի քանի հոգով խօսալ։ Սովորեցինք մեր բառերը ճիշտ օգտագործել խօսելու ժամանակ, քանի որ կամ Զումի 40 րոպէն էր աւարտուելու, կամ էլ ուզում էինք արագ խօսել ու անցնել իրական գործ անելու։ Ոչ միշտ, բայց դէ հիմնականում։

Հետաքրքիրն այն է, որ այդ բաները մեզ պէտք է արդէն սովորեցրած լինէին, չէ՞։ Դէ երեւի հասուն մարդ՝ adult լինելու կարիքներից մէկն է ոչ թէ միայն իմանալ այդ մասին, այլ նաեւ կիրառել։

Կարող ենք տարին համարել բաւարար սովորելու համար։

Աւաղ, մեզ այդպէս թուաց։ Քեզ էլ, չէ՞։ Մի անգամից պատերազմ, կռիւ, մահ, կորուստ։ Սպասում ես զանգի այն ընկերոջից, ում կարող է ժամանակին ժամերով անտեսէիր, քանի֊որ հիմա մտահոգ ես՝ հո բան չի՞ եղել։

Սպասում ես զանգի նոյնիսկ այն մարդկանցից, ովքեր գիտես ապահով են, քանի որ այսօր կայ, վաղը՝ չգիտես։ Եւ միշտ ուզում ես չիմացած ժամանակդ անցկացնել բոլորի հետ։

Վուդի Ալլէնի Café Society կինոի մէջ մի հաւէս պահ կար, ասում ա «Live every day like it could be your last and someday you’ll be right»։

Իրականում ահաւոր սկսել եմ գնահատել բոլոր օրերը։

Շատ անգամներ չեմ ասում, բայց նաեւ գնահատում եմ քեզ։ Գիտեմ, որ մէկ֊մէկ չես կարդում, մէկ֊մէկ մոռանում ես, որ ես գրում եմ։ Մոռացել ես RSS օգտագործել, կամ ինձ չես հետեւում, յղումը տեսնում ես, չես սեղմում։ Բայց ոչինչ, գիտեմ՝ մի օր կը կարդաս։ Շնորհակալ եմ, որ կարդում ես։

Ներկան՝ լաւ է։ Ոչ այդքան լաւ ինչքան կուզէի, բայց արի ու տես, որ այդ հին «խասեաթս» չեմ թողել՝ aiming higher, dreaming bigger։ Մինչ շատերը կասեն, որ իրականում երազկոտ եմ, ես կասէի՝ նպատակ֊ոտ եմ։

Ներկայի մասին խօսելը, ըստ իս, հիմնականում անիմաստ է։ Ներկայում պէտք է գործել։ Կարելի է, սակայն, խօսել ապագայի մասին, խօսել՝ ապագայի մասին, ներկայում՝ գործել։

Ոչ֊շատ֊ուշ մի քանի ծրագրի մասին կը հրապարակեմ, կամ ոնց ասում են՝ անօնս կանեմ։ Կիսուեմ քեզ հետ էլ։

Դէ գիտես, իմ առաջին կայքը պինգուինաշէն.ամ֊ն էր, ի շնորհիւ նորայրի եւ իմանդէսի, որտեղ իմ բլոգն էր, որտեղ մենք միասին ծանօթացանք։ Իրական նպատակն էր այնտեղ ունենալ համայնք, շատ հաւէս համայնք։ ֆորումի նման, հա ուզում էի HackerNews֊ի նման տեղ ունենալ, որտեղ մարդիկ հաւէս բաներ կը դնեն ու միասին կը քննարկենք այն։

Ահա եւ այն, կոչւում է Խօսենք, դէ քանի որ ուզում եմ միասին խօսենք։

Շատ մարդ չկայ, բայց երեւի կը շատանայ, մարդիկ կը գան, մենք էլ միասին կը խօսենք։ Խոստանում եմ կարգին հետեւել այն, լինել օրինապահ վարչապետ։

Այլ պլաննե՞ր։ հա, հա, կան։ Ընկերութիւնում ահագին բան առաջ է գնում, բայց դէ գիտես, ինքս ինձ հետ NDA ունեմ, այս պահին չեմ կարող պատմել։ Բայց երբ պատրաստ լինի ամէն ինչ, քեզ կասեմ։

Բա դո՞ւ, ո՞նց ես։ Գրիր ինձ, անպայման։ Ես քեզնից միշտ մեյլ եմ սպասում, մէկ մէկ գրում ես, մէկ մէկ՝ մոռանում։ Ոչինչ, գիտեմ, խառն ես։

Այլ բանե՞ր։ դէ, ասում են նիհարել եմ։ Ահագին կարողանում եմ ծոմապահել, շատ դէպքերում օրերով, ու մարզանք եմ անում։ Մի օր միասին գնանք վազելու, թայ֊չի անելու։

Մայրիկս բարեւներ ունի։

Քեզ անպայման լաւ կը նայես, ու դէ գիտես, բան պէտք լինի՝ հօս եմ։

Ասանկ բաներ…

Պատասխանել մեյլով

Ասք սրճարաններում մարդկանց հետ ծանօթանալու մասին

Իմ ամէն առաւօտը սկսում է կօֆէ խմելուց։ Կօֆէն ինձ համար շատ կարեւոր է, առանց կօֆէ օրը չի կարելի սկսել։

Շատ դէպքերում իմ օրը սկսում է ուրիշի հետ կօֆէ խմելուց, դրանք լինում են անձնական, գործնական եւ նոյնիսկ պետական հանդիպումներ։ Անպայման գնում ենք ինչ֊որ մի սրճարան՝ սրճելու։

Սրճարաններ շատ եմ սիրում, ու հիմնականում մի սրճարանից շատ եմ օգտւում, այնքան շատ, որ նոյնիսկ աշխատողներն են ինձ ճանաչում։ Օրինակ երբ մտնում եմ Դը Իտալեան, աշխատողները անպայման գալիս բարեւում են, խոհարարներին անձամբ շնորհակալութիւն եմ յայտնում։ Երբ նստում եմ, Էռնեստը կամ Սարոն մօտիկանում եւ ասում են «Լատէ՞, Մաքիատո՞» քանզի միշտ լատէ մաքիատո եմ խմում։

Սրճարանները նաեւ շատ եմ սիրում այն պատճառով, որ կարող եմ նոր մարդկանց հետ ծանօթանալ։

Այսօր գործնական հանդիպման սուրճով սկսաւ օրը։ Դուրս գալուց նկատեցի, որ մի երիտասարդ կողքի սեղանում նստած կոդագործում է։ Սկզբում ինձ թուաց, որ vim էր օգտագործում, շատ լաւ չէի տեսնում, դէ ակնոցս ջարդուել էր, բայց մի քիչ մօտիկացայ եւ ինձ թուաց որ IRC է մտել։ Պարզուեց, որ VS Code֊ով կոդ էր գրում։

Հիմա էստեղ կասէք «է հա, էնքան մարդ ա տենց», բայց ես կասեմ «այո, եւ բոլորի հետ ուզում եմ ծանօթանալ»։

Մօտիկացայ երիտասարդին, չհասկացայ, հայ էր թէ չէ, բայց ամէն դէպքում ասեցի՝ անգլերէնով «Օհ, փայթն էք գրում, ինչ հաւէս», ասաց՝ «այո այո, համեցիր, նստիր»։

Եւ ես նստեցի, ես մի ժամ զրուցեցինք։ Պարզուեց անունը Սամուէլ է, եւ ինքը դոկտորական աշխատանք է տանում Մաստրիխտի համալսարանում, որը վերաբերւում է Fuzzy Cognitive Map֊երին։ ահագին խօսեցինք ոլորտի վիճակի մասին, հայաստանի եւ նիդեռլանդների տարբերութեան մասին։ է֊մեյլներով փոխանակուեցինք եւ յոյս ունեմ մինչեւ իր գնալը կրկին կը տեսնեմ։

Ահա։ Եթէ մարդ էք տեսնում սրճարանում ապա անպայման մօտիկացէք, գուցէ նոր ծանօթ, բարեկամ, ընկեր, խնամի ձեռք բերէք։

ասանկ բաներ։

Պատասխանել մեյլով

Ի՞նչ եմ օգտագործում

Շատ անգամներ ինձ հարցնում են՝ «բա դու ի՞նչ ես օգտագործում», ու ես պէտք է երկար պատմեմ, թէ ինչ հարդուեր կամ սոֆթուեր եմ օգտագործում, սկսած ՕՀ֊ներից վերջացած ծրագրերով։

Այդ պատճառով որոշեցի գրել What I use էջը, որտեղ հատիկ֊հատիկ նշել եմ, թէ ինչ եմ օգտագործում, նոյնիսկ ժամացոյց, խցիկ, տետր, եւ այլն, իրենց համապատասխան յղումներով։

ասանկ բաներ։

Պատասխանել մեյլով

SSH գործակալ

Իհարկէ, շատ դէպքերում պէտք է լինում SSH-ուել սերւէրների մէջ։ հա լաւ, ամէն րոպէ էլ պէտք է լինում ։ՃՃ

Քանի ես դէմ եմ գաղտնաբառեր օգտագործելու ու սիրում եմ օգտագործել բանալիներ, ապա շատ եմ հաւաքում իմ SSH-ի բանալիների passphrase-ները։

Յիշեցի, որ դրա համար լուծում կայ. օգտագործել ssh-agent(1), որը իր յիշողութեան մէջ պահում ա passphrase-ը։

կարգաւորելու համար պէտք է աւելացնել հետեւեալը .bashrc ֆայլի մէջ.

eval $(ssh-agent -s) > /dev/null
trap "kill $SSH_AGENT_PID" 0

իսկ .ssh/config ֆայլի մէջ պէտք է աւելացնել

AddKeysToAgent yes

վերջ, հիմա մի անգամ բանալու passphrase-ը հաւաքելուց յետոյ այլեւս չի հարցնի։

ասանկ բաներ։

Պատասխանել մեյլով

WireGuard VPN FreeBSD֊ի վրայ

Արդէն քանի շաբաթ է ինչ Յուքոմը խափանում է նորմալ DNS֊ի աշխատանքը տան օգտատէրերի համար՝

antranigv@zvartnots:~ $ host jabber.am 37.252.73.34
;; connection timed out; no servers could be reached

բայց եթէ օգտագործենք յայտնի DNS սերւէրներ ապա խնդիր չի լինում՝

antranigv@zvartnots:~ $ host jabber.am 9.9.9.9
Using domain server:
Name: 9.9.9.9
Address: 9.9.9.9#53
Aliases: 

jabber.am has address 37.252.73.34
jabber.am mail is handled by 1 post.pingvinashen.am.

սա ստիպեց ինձ մտածել, թէ ինչպէս շատ արագ կարգաւորել VPN սերւէր, որը կը լինի պարզ։

Իհարկէ, մի քանի տարբեր կար մտքումս՝

  • OpenVPN
  • IKEv2
  • IPSec

Խնդիրը նրանում էր, որ այս երեքն էլ շատ բարդ են կարգաւորւում։ Հա, OpenVPN֊ը շատ ֆիչրներ ունի, բայց ես շատ բան չեմ ուզում։ IKEv2 կամ IPSec֊ն էլ շատ ձայնաւոր հաղորդակարգեր են։ ինձ աւելի պարզ բան էր պէտք։

Յիշեցի, որ վերջերս OpenBSD֊ի միջուկի մէջ ինտեգրել էին WireGuard֊ը։

Շատ կարճ պատմեմ WireGuard֊ի մասին։

  • շատ փոքր ծրագրային ապահովում. ~4000 տող կոդ, համեմատած ~100հազար տող կոդ OpenVPN֊ի
  • օգտագործում ա SSH֊ի authorized_keys֊ի նման մօտեցում
  • հեչ ձայնաւոր չի. մաքուր UDP֊ով ա աշխատում
  • մաքուր աշխատում ա routing table֊ի հետ։
  • կարծիքաւորուած ա

Հեղինակը շատ լաւ ներկայացնում ա այս հոլովակում։

Հիմա փորձելու եմ կարգաւորման քայլերը ցոյց տալ։ Ես օգտագործում եմ FreeBSD սերւեր բայց նոյնը հնարաւոր է անել լինուքսի վրայ ։)

մի քանի գլխաւոր գաղափարներ.

WireGuard֊ը ունի՝

  • Գաղտնի բանալի
  • UDP պորտ որին լսում է
  • կողմերի ցուցակ

կողմը ունի՝

  • իր համապատասխան հանրային բանալին
  • թունելի միջի IP հասցէն(երը)
  • (ոչ պարտադիր) վերջնակէտի IP հասցէն եւ պորտը

Լաւ, դէ կարգաւորենք։

Նախ երկու կողմերում քաշում ենք wireguard փեքիջը.

pkg install wireguard

սկսում ենք գաղտնի/հանրային բանալիներ ստեղծելով երկու կողմում.

umask 077
wg genkey > priv.key
wg pubkey < priv.key > pub.key

կապը աւելի անվտանգ դարձնելու համար կարող ենք նաեւ օգտագործել Preshared Key.

wg genpsk > one-psk-per-connection.psk

ապա սերւէրում գրում ենք՝ /usr/local/etc/wireguard/wg0.conf ֆայլի մէջ.

[Interface]
Address         = 10.0.0.1/24  # սերւէրի IP֊ն թունելի մէջ
ListenPort      = 1500         # UDP պորտը
PrivateKey      = (սերւէրի priv.key֊ի պարունակութիւն)

[Peer]
PublicKey       = (կլիենտի pub.key֊ի պարունակութիւն)
PresharedKey    = (one-psk-per-connection.psk-ի պարունակութիւն)
AllowedIPs      = 10.0.0.10/32 # կլիենտի IP֊ն թունելի մէջ

Այդքանը!

իսկ հիմա կլիենտում գրում ենք՝ wg0.conf ֆայլի մէջ.

[Interface]
PrivateKey   = (կլիենտի priv.key֊ի պարունակութիւն)
Address      = 10.0.0.10/24

[Peer]
PublicKey    = (սերւէրի pub.key֊ի պարունակութիւն)
PresharedKey = (one-psk-per-connection.psk֊ի պարունակութիւն)
Endpoint     = myserver:1500
AllowedIPs   = 0.0.0.0/0 # կամ 10.0.0.0/24 եթէ ուզում ենք ուղարկել միայն ներքին ցանցը

արդէն կարող ենք աշխատացնել

սերւէրում.

service wireguard enable
sysrc wireguard_interfaces="wg0"
service wireguard start

ու կլիենտում՝

wg-quick up /path/to/wg0.conf

Այսքանը!

եթէ հարցեր լինեն՝ you know where to find me 😉

ասանկ բաներ։

Պատասխանել մեյլով

Ասք DTrace-ով ծրագրերի հոսքը հետեւլու մասին

Մի շաբաթ առաջ գրառեցի թէ ինչպէս DTrace-ով վօկին հետեւել, այսօր ուզում եմ խօսել թէ ինչպէս հետեւլ ծրագրերին առհասարակ։

Վերցնենք էս օրինակը Սի-ով՝

#include <unistd.h>
#include <stdlib.h>

void a();
void b();

void a() {
  sleep(1);
};

void b() {
  sleep(1);
};

int main() {
  while (1) {
    a();
    b();
  };
  exit(0);
}

Հիմա փորձենք հետեւլ DTrace-ով՝

root@illuria-dev:~/voc-dtrace # dtrace -F -n 'pid$target:prog0::entry,pid$target:prog0::return{} tick-5s{exit(0)}' -c ./prog0
dtrace: description 'pid$target:prog0::entry,pid$target:prog0::return' matched 17 probes
CPU FUNCTION
  0  -> _start
  0    -> handle_static_init
  0    <- handle_static_init
  0    -> main
  0      -> a
  0      <- a
  0      -> b
  0      <- b
  0      -> a
  1      <- a
  1      -> b
  1      <- b
  1      -> a
  0       | :tick-5s

Ահա փաստօրէն կարողանում ենք նաեւ տեսնել թէ ֆունկցիան երբ ա մտնում ու երբ ա դուրս գալիս։

Մի փոքր բացատրեմ, ունենք provider, module, function, probe, նշել եմ որ ուզում եմ օգտագործել pid provider-ը, որը հետեւում է userland-ում կատարուող գործերին, մոդուլը դրել եմ ծրագրի անունը՝ prog0, ֆունկցիան էական չի, իսկ probe-ը նշել եմ եւ entry (մուտք) եւ return (էլք)։ Նաեւ նշել եմ, որ 5 վայրկեան յետոյ դուրս գայ։

Օկ հրաշալի, հիմա փորձենք օբերոնով գրած ծրագիր՝

MODULE prog1;

IMPORT Platform;

PROCEDURE A();
BEGIN
  Platform.Delay(1000)
END A;

PROCEDURE B();
BEGIN
  Platform.Delay(1000)
END B;

BEGIN
  WHILE TRUE
  DO
    A();
    B();
  END
END prog1.

Հիմա փորձենք հետեւել DTrace-ով՝

root@illuria-dev:~/voc-dtrace # dtrace -F -n 'pid$target:prog1::entry,pid$target:prog1::return{} tick-5s{exit(0)}' -c ./prog1
dtrace: description 'pid$target:prog1::entry,pid$target:prog1::return' matched 17 probes
CPU FUNCTION
  1  -> _start
  1    -> handle_static_init
  1    <- handle_static_init
  1    -> main
  1      -> prog1_A
  1      <- prog1_A
  1      -> prog1_B
  1      <- prog1_B
  1      -> prog1_A
  1      <- prog1_A
  1      -> prog1_B
  1      <- prog1_B
  1      -> prog1_A
  0       | :tick-5s

Ահ, մի բան էն չի։ հմմ։ երեւի վօկի գեներացրած կոդից ա՝

/* voc 2.1.0 [2020/07/14] for clang LP64 on freebsd xtpam */

#define SHORTINT INT8
#define INTEGER  INT16
#define LONGINT  INT32
#define SET      UINT32

#include "SYSTEM.h"
#include "Platform.h"

static void prog1_A (void);
static void prog1_B (void);

static void prog1_A (void)
{
  Platform_Delay(1000);
}

static void prog1_B (void)
{
  Platform_Delay(1000);
}

export int main(int argc, char **argv)
{
  __INIT(argc, argv);
  __MODULE_IMPORT(Platform);
  __REGMAIN("prog1", 0);
/* BEGIN */
  while (1) {
    prog1_A();
    prog1_B();
  }
  __FINI;
}

Հա, փաստօրէն վօկի գեներացրած կոդից ա։

Լաւ, ենթադրենք սա իրական ծրագիր ա, ու ուզում ենք իմանալ ուր ա bottleneck-ը, պէտք է հասկանալ ամենաերկարը որտեղ ա ծրագրին երկար տեւում։

pid$target:prog1::entry
{
        self->ts = timestamp;
}

pid$target:prog1::return
/self->ts/
{
        @time[probefunc] = sum(timestamp - self->ts);
        self->ts = 0;
}

tick-5s
{
        exit(0)
}

Էս դէպքում ֆունկցիայի մէջ մտնելու ժամանակ ասում եմ որ ts փոփոխականի մէջ նշի timestamp-ը, ու ելքի ժամանակ ստուգել եթէ ts փոփոխականը յայտարարուած ա։

@time[probefunc] = sum(timestamp - self->ts); տողի վրայ ագրիգացիա է կատարւում գումարելով (sum) թէ ինչքան ժամանակ է տեւել մտնելուց մինչեւ դուրս գալը (timestamp - self->ts) ու պահում time փոփոխականի մէջ։

5 վայրկեան յետոյ դուրս է գալիս ։)

ահա՝

root@illuria-dev:~/voc-dtrace # dtrace -s prog1.d -c ./prog1
dtrace: script 'prog1.d' matched 17 probes
CPU     ID                    FUNCTION:NAME
  0  72544                         :tick-5s

  handle_static_init                                             5137
  prog1_A                                                  2057419770
  prog1_B                                                  2063438603

էսօրուայ համար էսքանը։

ասանկ բաներ։

Պատասխանել մեյլով

Ասք DTrace-ով վօկին հետեւելու մասին

Մի քանի օր առաջ իմ անգլերէն մատեանում գրառել էի թէ ինչպէս Erlangի վիրտուալ մեքենան հետեւել, ու «ցանցառներ ռադիօ»-ի ժամանակ նորայրը հարցրեց եթէ նման բան կարող ենք անել կոմպիլացուած լեզուների վրայ։

Իհարկէ հնարաւոր է, բայց դէ մեզ պէտք է ինչ-որ հետեւելու համակարգ, օրինակ DTrace կամ eBPF։

Իհարկէ DTrace ամէն օր օգտագործում եմ, այնպէս որ մտածեցի, ինչ վատ կը լինի, եթէ փորձեմ վօկ-ի հետ աշխատեցնել ։)

MODULE prog0;

IMPORT Out;

BEGIN
  Out.String("Hello, World!"); Out.Ln;
END prog0.

կոմպիլացնենք ու աշխատեցնենք՝

root@illuria-dev:dtrace # voc -m prog0.Mod
prog0.Mod  Compiling prog0.  Main program.  383 chars.
root@illuria-dev:dtrace # ./prog0
Hello, World!

Շատ լաւ, հրաշալի։

Հիմա ինձ պէտք է իմանալ, թէ prog0 պրոցեսը առհասարակ ինչ ֆունկցիաներ է կանչում։

փորձարկում առաջին՝

փորձեմ տեսնել ամէն ինչ որը կանչում է prog0-ն, ապա գրում եմ all.d ֆայլի մէջ՝

pid$target:::
{
        printf("%s:%s:%s:%s\n", probeprov, probemod, probefunc, probename);
}

ու հիմա աշխատեցնեմ՝

root@illuria-dev:dtrace # dtrace -s all.d -c ./prog0
dtrace: failed to compile script all.d: line 1: failed to create offset probes in 'ethZip_ReadBytes': Cannot allocate memory

Հմմ, memory allocation խնդիր է։ լաւ, փորձեմ աւելի քիչ բան կանչել։ տեսնես ի՞նչ գրադարաններ եւ/կամ ռանթայմեր է կանչում prog0-ն։

root@illuria-dev:dtrace # ldd ./prog0
./prog0:
        libvoc-O2.so => /usr/local/share/voc/lib/libvoc-O2.so (0x800249000)
        libc.so.7 => /lib/libc.so.7 (0x80034f000)

Լաւ, լաւ, կարող եմ միայն libvoc-O2-ին կանչել ։)

սարքում եմ libvoc.d ֆայլ, մէջը գրում եմ՝

pid$target:libvoc-O2::entry
{
        printf("%s:%s:%s:%s\n", probeprov, probemod, probefunc, probename);
}

ու կանչում եմ՝

root@illuria-dev:dtrace # dtrace -s libvoc.d -c ./prog0 -o libvoc.out
dtrace: script 'libvoc.d' matched 1651 probes
Hello, World!
dtrace: pid 64686 has exited

ահ, 1651 հատ տուեալների մուտք կայ։ դէ կարդանք մեր output-ը՝

     1	CPU     ID                    FUNCTION:NAME
     2	  0 262042               Modules_Init:entry pid64686:libvoc-O2.so:Modules_Init:entry
     3	  0 261868              Heap_InitHeap:entry pid64686:libvoc-O2.so:Heap_InitHeap:entry
     4	  0 261751        Platform_OSAllocate:entry pid64686:libvoc-O2.so:Platform_OSAllocate:entry
     5	  0 261679                 Heap__init:entry pid64686:libvoc-O2.so:Heap__init:entry
     6	  0 262691                Heap_REGMOD:entry pid64686:libvoc-O2.so:Heap_REGMOD:entry
     7	  0 261956                Heap_NEWREC:entry pid64686:libvoc-O2.so:Heap_NEWREC:entry
     8	  0 262116                Heap_REGCMD:entry pid64686:libvoc-O2.so:Heap_REGCMD:entry
     9	  0 261956                Heap_NEWREC:entry pid64686:libvoc-O2.so:Heap_NEWREC:entry
    10	  0 262116                Heap_REGCMD:entry pid64686:libvoc-O2.so:Heap_REGCMD:entry
    11	  0 261956                Heap_NEWREC:entry pid64686:libvoc-O2.so:Heap_NEWREC:entry
    12	  0 262116                Heap_REGCMD:entry pid64686:libvoc-O2.so:Heap_REGCMD:entry
    13	  0 261956                Heap_NEWREC:entry pid64686:libvoc-O2.so:Heap_NEWREC:entry
    14	  0 262116                Heap_REGCMD:entry pid64686:libvoc-O2.so:Heap_REGCMD:entry
    15	  0 261956                Heap_NEWREC:entry pid64686:libvoc-O2.so:Heap_NEWREC:entry
    16	  0 262180             SYSTEM_INHERIT:entry pid64686:libvoc-O2.so:SYSTEM_INHERIT:entry
    17	  0 262180             SYSTEM_INHERIT:entry pid64686:libvoc-O2.so:SYSTEM_INHERIT:entry
    18	  0 262180             SYSTEM_INHERIT:entry pid64686:libvoc-O2.so:SYSTEM_INHERIT:entry
    19	  0 262180             SYSTEM_INHERIT:entry pid64686:libvoc-O2.so:SYSTEM_INHERIT:entry
    20	  0 262570              Modules__init:entry pid64686:libvoc-O2.so:Modules__init:entry
    21	  0 261679                 Heap__init:entry pid64686:libvoc-O2.so:Heap__init:entry
    22	  0 261970                Heap_INCREF:entry pid64686:libvoc-O2.so:Heap_INCREF:entry
    23	  0 262511             Platform__init:entry pid64686:libvoc-O2.so:Platform__init:entry
    24	  0 262691                Heap_REGMOD:entry pid64686:libvoc-O2.so:Heap_REGMOD:entry
    25	  0 261956                Heap_NEWREC:entry pid64686:libvoc-O2.so:Heap_NEWREC:entry
    26	  0 261924                Heap_REGTYP:entry pid64686:libvoc-O2.so:Heap_REGTYP:entry
    27	  0 262180             SYSTEM_INHERIT:entry pid64686:libvoc-O2.so:SYSTEM_INHERIT:entry
    28	  0 262461                 SYSTEM_DIV:entry pid64686:libvoc-O2.so:SYSTEM_DIV:entry
    29	  0 261970                Heap_INCREF:entry pid64686:libvoc-O2.so:Heap_INCREF:entry
    30	  0 262691                Heap_REGMOD:entry pid64686:libvoc-O2.so:Heap_REGMOD:entry
    31	  0 261956                Heap_NEWREC:entry pid64686:libvoc-O2.so:Heap_NEWREC:entry
    32	  0 262685    Platform_IdentifyByName:entry pid64686:libvoc-O2.so:Platform_IdentifyByName:entry
    33	  0 263025                  Out__init:entry pid64686:libvoc-O2.so:Out__init:entry
    34	  0 261679                 Heap__init:entry pid64686:libvoc-O2.so:Heap__init:entry
    35	  0 261970                Heap_INCREF:entry pid64686:libvoc-O2.so:Heap_INCREF:entry
    36	  0 262511             Platform__init:entry pid64686:libvoc-O2.so:Platform__init:entry
    37	  0 261970                Heap_INCREF:entry pid64686:libvoc-O2.so:Heap_INCREF:entry
    38	  0 262691                Heap_REGMOD:entry pid64686:libvoc-O2.so:Heap_REGMOD:entry
    39	  0 261956                Heap_NEWREC:entry pid64686:libvoc-O2.so:Heap_NEWREC:entry
    40	  0 262116                Heap_REGCMD:entry pid64686:libvoc-O2.so:Heap_REGCMD:entry
    41	  0 261956                Heap_NEWREC:entry pid64686:libvoc-O2.so:Heap_NEWREC:entry
    42	  0 262116                Heap_REGCMD:entry pid64686:libvoc-O2.so:Heap_REGCMD:entry
    43	  0 261956                Heap_NEWREC:entry pid64686:libvoc-O2.so:Heap_NEWREC:entry
    44	  0 262116                Heap_REGCMD:entry pid64686:libvoc-O2.so:Heap_REGCMD:entry
    45	  0 261956                Heap_NEWREC:entry pid64686:libvoc-O2.so:Heap_NEWREC:entry
    46	  0 262886         Platform_IsConsole:entry pid64686:libvoc-O2.so:Platform_IsConsole:entry
    47	  0 261970                Heap_INCREF:entry pid64686:libvoc-O2.so:Heap_INCREF:entry
    48	  0 262691                Heap_REGMOD:entry pid64686:libvoc-O2.so:Heap_REGMOD:entry
    49	  0 261956                Heap_NEWREC:entry pid64686:libvoc-O2.so:Heap_NEWREC:entry
    50	  0 262286                 Out_String:entry pid64686:libvoc-O2.so:Out_String:entry
    51	  0 262704                     Out_Ln:entry pid64686:libvoc-O2.so:Out_Ln:entry
    52	  0 261895             Platform_Write:entry pid64686:libvoc-O2.so:Platform_Write:entry
    53	  0 262517                Heap_FINALL:entry pid64686:libvoc-O2.so:Heap_FINALL:entry

ահ, հրաշալի, տող 50-ում կանչում ա Out.String

հիմա կարող ենք փորձել դինամիք կերպով կանչել իրա առաջին արգումենտը ։)

գրում եմ string_arg.d ֆայլի մէջ՝

pid$target:libvoc-O2:Out_String:entry
{
        printf("Function Out.String has run with arguments: %s", copyinstr(arg0));
}

ու աշխատեցնում եմ՝

root@illuria-dev:dtrace # dtrace -qs string_arg.d -c ./prog0
Hello, World!
Function Out.String has run with arguments: Hello, World!

Ահ, հրաշալի՜

Լաւ, հիմա փորձեմ more dirty stuff 😉

ունենք prog1.Mod

MODULE prog1;

IMPORT Out, In;

VAR s: ARRAY 32 OF CHAR;
BEGIN
  In.Line(s); Out.Ln;
END prog1.

ու նաեւ հետեւլեալ D ծրագիրը՝

pid$target:libvoc-O2:Platform_ReadBuf:entry
{
        printf("Function Platform.Readbuf has run with arguments: %s\n", copyinstr(arg1));
}

ահա!

root@illuria-dev:dtrace # voc -m prog1.Mod
prog1.Mod  Compiling prog1.  Main program.  435 chars.
root@illuria-dev:dtrace # dtrace -qs in.d -c ./prog1
Function Platform.Readbuf has run with arguments:
myinput!

Function Platform.Readbuf has run with arguments: m
Function Platform.Readbuf has run with arguments: y
Function Platform.Readbuf has run with arguments: i
Function Platform.Readbuf has run with arguments: n
Function Platform.Readbuf has run with arguments: p
Function Platform.Readbuf has run with arguments: u
Function Platform.Readbuf has run with arguments: t
Function Platform.Readbuf has run with arguments: !

root@illuria-dev:dtrace #

Այնպէս որ, հա՛։ DTrace-ը փաստացի rootkit է ։)

ասանկ բաներ։

Պատասխանել մեյլով

Ասք թերթերի մասին

Այսօր ահագին բլբլացել եմ թութում եւ թվիթերում ժամանակակից մամուլի բումի եւ թերթերի մասին։ Ուզում եմ նոյնը նաեւ գրել այստեղ, Հայերէնով։

Այս ինֆորմացիայի դարի ժամանակ ահագին բարդ է պահպանել առողջութիւնը լուրերը կարդալու ժամանակ, շատ բարդ է իմանալ թէ ինչ է կատարւում երկրի մը մէջ, երբ ամէն մի յօդուած ներկայացնում է տուեալների բիթեր առանց ոչ մի տեղեկատուութեան։

Հենց այդ պատճառով մի քանի ամիս առաջ որոշեցի կարդալ թերթեր։ այո, թղթով տպած թերթեր։

Երեք գլխաւոր բաներ են կատարւում երբ կարդում ես թերթ։

Առաջին. Տուեալները սկսում են իրար հետ կապ ունենալ։ Այսօր կարդում ես շատ փոքր նորութիւն, մէկ շաբաթ յետոյ կարդում ես այդ լուրի զարգացումները։ TL;DR՝ չես կորում։

Երկրոդ. Մարդկանց տալիս է հարթակ, որտեղ կարող են արտայայտել իրենց մտքերը եւ տեսակէտը ինչ որ հարցի շուրջ, դա լինի քաղաքական, արուեսի, մշակոյթի կամ իրենց յուզող խնդրի մասին։

Երրորդ. Մարդիկ, մանաւանդ ջահելները, սկսում են շատ տարօրինակ նայել։ Երբ նստում եմ սրճարանում եւ պայուսակիցս հանում եմ թերթը, ինձ նայում մտածելով «էս թե՞րթ ա կարդում։ բայց ինքը պապի չի։ ախր Այֆոն ու ՄակԲուք ունի։ ինչի՞»։

TL;DR: Թերթերը շատ լաւն են, առցանց տուեալների բումը չի նշանակում որ թերթերը վերացել են, ոչ էլ պէտք է նշանակի այն։

Գնի՛ր Թերթ մը, Փրկի՛ր Լրագրութիւնը։

Պատասխանել մեյլով

Վատ միգրացիայի մասին

մօտ մէկ տարի առաջ խօստացել էի, որ կրկին գրելու եմ մատեանում։ Սակայն կեանքը նենց բան ա, որ մի օր խօստանում ես, ու յաջորդ օրը արդէն սկսում ես գործերով խառը լինել։

Միւս պատճառներից մէկը, որ չէի գրառում, այն էր, որ Հուգո գաղթ անելուց յետոյ, մատեանում ահագին խնդիրներ կային, մանաւանդ մեդիաների հետ, նկարները ցոյց չէր տալիս, իսկ վիդեոները չկան։

մի փոքր պատմեմ, թէ ինչպէս յունիքսի գործիքները օգտագործելով աւտոմատ հետ բերեցի նկարները։

Նախ պէտք է հասկանալ թէ ինչումն է խնդիրը։ MarkDown նիշերը բացելուց յետոյ, տեսայ որ նկարների պիտակն էր սխալ։ ՄարքԴաունում պէտք է լինի

![alt text](image.jpg)

Սակայն իմ մօտ WordPressից Hugo convert անելու ժամանակ այսպէս էր փոխուել՝

[<img src="հասցէ" ալտ="ինֆո"/>](հասցէ)

շատ լաւ, ուրեմն պէտք էր բոլոր ֆայլերի մէջ աւելացնել ! նշանը։
Բացի դրանից, պէտք էր հաստատ իմանալ, որ նկար ա, ու քանի որ converterը հենց [<img>](src) ֆորմատով էր սարքում, կարելի է ենթադրել, որ եթէ ունենք [<img ուրեմն դա նկար է, ու կարող ենք աւելացնել ! տառը։

պէտք է ընդամէնը մի հատ հրաման աշխատեցնել։

sed -i ''  's/\[<img/![<img/g' *

Եւ ահա, բոլոր նկարները հետ յայտնուեցին ։) օր՝ Լեգգի տառատեսակ

յաջորդ քայլը պէտք է լինի, թէ ինչպէս հետ բերել վիդէոների լինքերը։

ասանկ բաներ

Պատասխանել մեյլով

Ասք տաս տարեկան լինուքս հեռախօսով հաղորդագրութիւն ուղարկել եւ ստանալու մասին

նախաբան

Շաբաթ իրիկուն էր։ Գնացել էի ISTC մի քանի հատ սպասարկիչ թարմացնելու համար։ Ընկերներս այնտեղ էին, ու պարզւում է, որ հաքաթոն էր։ Թեման՝ Օփըն Գավըրնմընթ։

Ընկերներիս հարցրեցի «ինչո՞վ կարող եմ օգնել»։ ասեցին «արի փորձի Twilio-ի կամ այլ հաղորդագրութիւն ուղարկող/ստացող ծառայութիւն տրամադրող ընկերութեան հետ կպնել»։

դէ լաւ։ ինչքա՞ն բարդ կարող է լինել։ ունեն հաւանաբար մի հատ HTTP API, նայեցի, սիրուն ԱՊԻ-ներ ունէին։

դէ լաւ, գրանցուեցի մէկն ու մէկի մօտ, բայց արի ու տես, որ Հայաստանին ոչ մէկ բանի տեղ չի դնում (յետոյ էլ ասում են թէ մեր մօտ ՏՏ-ն զարգացած ա)։

ստանալ

իհարկէ, ես սիրում եմ ամէն ինչ իմ ձեռքերով անել։ ու ես ունեմ Նոկիա Ն900։ ու ինքը աշխատում ա լինուքսով, աւելի կոնկրետ՝ Մաեմոյով։

Շատ լաւ, մի քիչ research արեցի, ու պարզուեց, որ կարող եմ հաղորդագրութիւնները կարդալ D-Bus-ից օգտուելով։ Ինչ-որ փոքր փայթն ծրագիր էր, սակայն չէր աշխատում։ ու քանի որ հաքաթոն էր, ինձ պէտք էր ուղղակի աշխատեցնել այն շատ արագ, մի քանի րոպէ աչքով դիբագ արեցի ու վերջում ստացայ այս կոդը

#!/usr/bin/env python2.5
import sched, time
import dbus
import gobject
from dbus.mainloop.glib import DBusGMainLoop
import subprocess
import httplib, urllib

def octify(str):
        '''
        Returns a list of octet bytes representing
        each char of the input str.
        '''

        bytes = map(ord, str)
        bitsconsumed = 0
        referencebit = 7
        octets = []

        while len(bytes):
                byte = bytes.pop(0)
                byte = byte >> bitsconsumed

                try:
                        nextbyte = bytes[0]
                        bitstocopy = (nextbyte & (0xff >> referencebit)) << referencebit
                        octet = (byte | bitstocopy)

                except:
                        octet = (byte | 0x00)

                if bitsconsumed != 7:
                        octets.append(byte | bitstocopy)
                        bitsconsumed += 1
                        referencebit -= 1
                else:
                        bitsconsumed = 0
                        referencebit = 7

        return octets

def semi_octify(str):
        '''
        Expects a string containing two digits.
        Returns an octet -
        first nibble in the octect is the first
        digit and the second nibble represents
        the second digit.
        '''
        try:
                digit_1 = int(str[0])
                digit_2 = int(str[1])
                octet = (digit_2 << 4) | digit_1
        except:
                octet = (1 << 4) | digit_1

        return octet


def deoctify(arr):

        referencebit = 1
        doctect = []
        bnext = 0x00

        for i in arr:

                bcurr = ((i & (0xff >> referencebit)) << referencebit) >> 1
                bcurr = bcurr | bnext

                if referencebit != 7:
                        doctect.append( bcurr )
                        bnext = (i & (0xff << (8 - referencebit)) ) >> 8 - referencebit
                        referencebit += 1
                else:
                        doctect.append( bcurr )
                        bnext = (i & (0xff << (8 - referencebit)) ) >> 8 - referencebit
                        doctect.append( bnext )
                        bnext = 0x00
                        referencebit = 1

        return ''.join([chr(i) for i in doctect])


def createPDUmessage(number, msg):
        '''
        Returns a list of bytes to represent a valid PDU message
        '''
        numlength = len(number)
        if (numlength % 2) == 0:
                rangelength = numlength
        else:
                number = number + 'F'
                rangelength = len(number)

        octifiednumber = [ semi_octify(number[i:i+2]) for i in range(0,rangelength,2) ]
        octifiedmsg = octify(msg)
        HEADER = 1
        FIRSTOCTETOFSMSDELIVERMSG = 10
        ADDR_TYPE = 129 #unknown format
        number_length = len(number)
        msg_length = len(msg)
        pdu_message = [HEADER, FIRSTOCTETOFSMSDELIVERMSG, number_length, ADDR_TYPE]
        pdu_message.extend(octifiednumber)
        pdu_message.append(0)
        pdu_message.append(0)
        pdu_message.append(msg_length)
        pdu_message.extend(octifiedmsg)
        return pdu_message


def sendmessage(number, message):

        bus = dbus.SystemBus()
        smsobject = bus.get_object('com.nokia.phone.SMS', '/com/nokia/phone/SMS/ba212ae1')
        smsiface = dbus.Interface(smsobject, 'com.nokia.csd.SMS.Outgoing')
        arr = dbus.Array(createPDUmessage(number.replace('+', '00'), message))

        msg = dbus.Array([arr])
        smsiface.Send(msg,'')


def callback(pdumsg, msgcenter, somestring, sendernumber):

        msglength = int(pdumsg[18])
        msgarray = pdumsg[19:len(pdumsg)]

        msg = deoctify(msgarray)

        if msg > 0:
               print 'New message received from %s' % sendernumber
               print 'Message length %d' % msglength
               print 'Message: %s' % msg
               params = urllib.urlencode({'answer': msg})
               headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
               conn = httplib.HTTPConnection("sms.myserver.am:80")
               conn.request("POST", "/sms", params, headers)
               conn.close()


def listen():
        DBusGMainLoop(set_as_default=True)
        bus = dbus.SystemBus() #should connect to system bus instead of session because the former is where the incoming signals come from
        bus.add_signal_receiver(callback, path='/com/nokia/phone/SMS', dbus_interface='Phone.SMS', signal_name='IncomingSegment')
        gobject.MainLoop().run()


if __name__ == '__main__':
  import time

  def schedule_task(schedule, fn, *args):
      import sched
      s = sched.scheduler(time.time, time.sleep)
      startTime = time.mktime(time.strptime(schedule, '%b %d %H:%M %Y'))
      s.enterabs(startTime, 0, fn, args)
      s.run()

  import getopt, sys
  try:
    opts, args = getopt.getopt(sys.argv[1:],"hlt:", ["help","listen","time="])

  except getopt.GetoptError, err:
    # print help information and exit:
    print str(err) # will print something like "option -a not recognized"
    usage()
    sys.exit(2)
  listening = False
  timeofday = ''
  for opt, arg in opts:
    if opt in ("-h", "--help"):
      usage()
      sys.exit()
    elif opt in ("-l", "--listen"):
      listening = True
    elif opt in ("-t", "--time"):
      timeofday = arg
    else:
      assert False, "unhandled option"

  listen()

Հետաքրքիր բաները կատարւում են listen() եւ callback() ֆունկցիաների մէջ։ listen()-ը լսում ա SMS-ներին, օգտագործելով D-Bus, ու SMS ստանալուց կանչում է callback() ֆունկցիան, որտեղ փոփոխութիւններ եմ կատարել։

Օգտագործելով urllib եւ httplib աւանդական գրադանները, POST հարցում եմ ուղարկում ոմն sms.myserver.am-ին։

ուղարկել

Հաղորդագրութիւն ուղարկելու համար, ես վստահ էի, որ ինչ-որ մէկը, հաստատ մի ծրագիր գրել է, ապա ման եկայ Մաեմոյի շտեմարանում ու գտայ smssend ծրագիրը։

Շատ լաւ, հեռախօսի վրայ աշխատեցնում եմ

apt-get update # հազարի տարի է update չեմ արել
apt-get install smssend

շաաաատ լաւ, հիմա արդէն, պէտք է աւտոմատ ձեւով սպասարկչից ստանամ թէ որ հեռախօսահամարին ինչ պէտք է ուղարկեմ, եւ վերջ, ապա մի քանի րոպէում գրում եմ polling անող ծրագիր HTTP-ի համար։ ջահելները սրան ասում են ծիպը բզող տեխնոլոգիա։

ահա եւ կոդը։

#!/usr/bin/env python2.5
import subprocess
import httplib, urllib
import simplejson as json
import time


def send_sms(num, text):
    print "sending sms"
    subprocess.Popen(["smssend", "-s", "-n", num, "-m", text])


def loop_fetch():
    conn = httplib.HTTPConnection("sms.myserver.am:80")
    conn.request("GET", "/sms")
    s = conn.getresponse().read()
    if s != 'false':
        j = json.loads(s)
        send_sms(j['number'], j['text'])
    time.sleep(10)
    print "waking up"
    loop_fetch()

def loop():
    loop_fetch()

if __name__ == '__main__':
    print "hello!"
    loop()

վերջաբան

ահա, հիմա բացում եմ երկու հատ տերմինալ, ու երկու ծրագրերն էլ աշխատեցնում եմ։

$ chmod +x sms.py
$ ./sms.py
$ chmod +x poll.py
$ ./poll.py

Գնում եմ տղաների մօտ եւ ուրախանալով ասում «տղանե՜ր, չscalable Twilio եմ սարքել»։

ասանկ բաներ…

Պատասխանել մեյլով