jiyuu-מחשבות פתוחות

התפרצויות כתיבה

30/06/2008 08:12 ע"י כתריאל טראום

הרבה זמן כבר לא כתבתי כאן.
מודה, קצת היתה חסרה לי מוזה. אם אין לי מוזה, אני לא כותב. ככה זה גם כשאני כותב קוד, יש לי לפעמים "התפרצויות כתיבה" בהן אני מסוגל לכתוב אפליקציה שלמה, או לגמור איזה feature שרציתי להוסיף ל-Jiyuu במכה.

יצא לי היום לקרוא קצת את ה-Planet של המקור, וקפץ לעיני הפוסט של נדב על חוסר עדכון הבלוג שלו. קצת חרגתי משלושת שבועות שלו, אבל ניחא. Better late than never.

אז מה חדש… מערכת ההתקנה שכתבתי ב-Python פחות או יותר הושלמה, ועושה את המלאכה בצורה די טובה. שמחתי שיצא לי לכתוב אותה, למדתי הרבה על Python, דברים כמו שימוש במחלקות (Classes), שגיאות (Exceptions) ומודולים. כמובן שיש עוד המון ללמוד, והפרויקט הבא כבר בדרך.

הפרויקט הבא דווקא לא קשור ישירות ל-Python, אבל יש לי כוונה להשתמש בו למרות זאת. עלה צורך בעבודה לנתח מספר רב של קבצי tcpdump בפורמט pcap ולחלץ מהם קצת מידע וסטטיסטיקות. עם כל ההייפ לאחרונה סביב Cloud Computing, החלטתי גם לקפוץ על העגלה. הכוונה היא להשתמש ב-hadoop שרץ על כמה מכונות וירטואליות שמפוזרות על כמה מכונות פיזיות כדי לחלק ולבזר את פעולת הניתוח. איך Python קשור? למרות ש-hadoop כתוב ב-java ומספק API ל-java, יש אפשרות להתממשק אליו בעזרת streams. הכוונה היא לשלב את hadoop יחד עם Python ו-pylibpcap כדי לחלץ את המידע הרלווטי ולסכם אותו תוך שימוש במנגנון MapReduce.

קצת שאפתני, אני יודע. אבל אם לא שואפים גבוהה, לא לומדים.

זהו בנתיים. עדכונים ואולי איזה מדריכון על hadoop בקרוב.

SQLite ו-Full Text Search

15/05/2008 22:15 ע"י כתריאל טראום

כאשר הוספתי יכולות חיפוש ל-Jiyuu, החלטתי קודם לבדוק האם יש ל-SQLite יכולות של Full Text Searching. לשמחתי ולדאבוני, גיליתי כי יכולת כזו קיימת, אך רק כהרחבה, אשר אינה זמינה ברוב אם לא בכל ההפצות כיום. מסיבה זו החלטתי להשתמש בשאילתות סטנדרטיות עם LIKE.

כאשר בחנתי את הרחבת ה-Full Text Search גיליתי כי היא מעניינת ומלאת אפשרויות, ולכן החלטתי לחקור אותה קצת ולשתף אתכם עם המסקנות.

הקדמה קצרה

Full Text Search היא טכניקת חיפוש שמאפשרת חיפוש מהיר (בד"כ) בכמות גדולה של מסמכים או כל מקור טקסט אחר. כאשר כמות המסמכים שיש לחפש בהם היא קטנה, ביצע חיפוש רגיל (חיפוש סריאלי או סדרתי) בד"כ יספק תוצאות במהירות סבירה יחסית. אבל מה עושים כאשר יש מאות או אלפי מסמכים לחפש בהם?

Full Text Searching (או FTS) היא טכניקה אשר מחולקת ל-2 חלקים: יצירת Index וחיפוש:

  • יצירת Index הוא תהליך של מיפוי הטקסט או טקסטים ויצירת Index בר-חיפוש של הטקסט.
  • תהליך החיפוש הוא תהליך שליפת המידע. החיפוש עצמו לא ניגש לטקסטים אלא ל-Index שנוצר מבעוד מועד ומאפשר שליפה מהירה של הטקסט, בלי סריקה מלאה שלו.

דוגמה קלאסית מעולם הקוד הפתוח לאפליקציית Full Text Searching היא Beagle אשר משתמש במנוע Indexing בשם Lucene, ליצירת Index של מידע אישי ואחזור מהיר שלו (מסמכים\אימיילים ועוד).

FTS ו-SQLite

בעולם מסדי הנתונים, שימוש ב-FTS אינו קיים או מוגדר כתקן (ANSI SQL), ובד"כ אם יש אפשרות כזו, זו היא הרחבה של מסד הנתונים.

יש הטוענים, ובצדק, כי מסד נתונים הוא אינו המקום לאחסן כמויות או את סוג המידע שיצריך שימוש ב-FTS. לראיה, מספר הפרויקטים\מוצרים (פתוחים או לא) אשר מיישים FTS לאחזור מידע וטקסט (ואינם מסדי נתונים) הוא די גדול.

אבל אני טוען, כי בימינו, כמות המידע אשר נדחס לתוך מסדי נתונים הולך וגדל. עם העליה של כמות הבלוגים והתוכן בהם, כמות אתרי החדשות והתוכן בהם וכו', השימוש ב-FTS כבר לא כל כך מופרך במסדי נתונים.

SQLite, כמו מסדי נתונים אחרים, מיישם גם הוא FTS, כהרחבה, אשר לצערי עדיין אינה נכללת ברוב ההפצות. קימפול של sqlite עם FTS הוא יחסית פשוט ומוסבר בקישור הבא. שימו לב כי ההוראות הן לגבי fts1 אבל נכונות גם לגרסאות החדשות יותר fts2\fts3 אשר נכללות בגרסאות האחרונות של sqlite.

בניית טבלאת FTS

לאחר בנייה של sqlite עם fts3, ניתן להתחיל לצור טבלאות אשר יבנו Index של המידע שנוסף אליהן. כדי לבנות טבלה אשר תשתמש ב-FTS משתמשים בתחביר הבא:

create virtual table email using fts3(subject, content)

פקודה זו תצור טבלה אשר יבנה לה Index מסוג FTS, ותאפשר אחזור מידע בעזרת פקודות SQL מתאימות.

הכנסת מידע

הכנסת מידע לטבלה נעשית בצורה סטנדרטית, ללא צורך בשינוי התחביר הסטנדרטי של SQLite

INSERT INTO email (subject, content) VALUES \
('meeting summary','summary for tuesday 23rd meeting \
 about bugs in the soup');
INSERT INTO email (subject, content) VALUES \
('trip plans','trip plans for upcoming flight to europe');

אחזור מידע

באחזור המידע מתגלה הכח והגמישות של הרחבת ה-FTS של SQLite. ההרחבה מאפשרת שליפה לא רק מהירה יותר כאשר מדובר בכמות מסמכים גדולה, אלא גם גמישה. שליפה סטנדרטית היא בעזרת שימוש במילת הברירה MATCH:

sqlite> SELECT subject, content FROM email \
WHERE content MATCH 'soup';
meeting summary|summary for tuesday 23rd meeting about bugs in the soup

FTS מאפשר שליפות שונות נוספות, למשל שליפה עם שלילה של מילים:

sqlite> SELECT * FROM email WHERE content MATCH 'for -meeting';
trip plans|trip plans for upcoming flight to europe

מכיוון ששאילתות FTS יכולות להכיל רק MATCH אחד, ניתן גם להשתמש בשם העמודה בשאילתה:

sqlite> SELECT subject FROM email where email MATCH \
'subject:plans content:europe';

trip plans

מכיוון שכל המידע שנשמר בטבלאות FTS הוא מידע שעובר אינדוקס מלא, לפעמים נוטים לחלק את הטבלאות ל-2: טבלאות metadata וטבלאות FTS. ניתן לאחזר מידע ע"י שימוש ב-JOIN וכך לקבל את כל המידע בשאילתה אחת. למשל הרצף הבא יחזיר את כל כותרות האימיילים והשולח שלהם שמכילים את המילה "some":

sqlite> create virtual table email using fts3(subject, content);
sqlite> create table email_meta (sender text, date integer);
sqlite> insert into email_meta values ('abc@def.com', 1210878295);
sqlite> insert into email values ('email from me','with some content');
sqlite> select sender, subject from email_meta join email_body \
 on email_meta.rowid = email_body.rowid where content match 'some';

abc@def.com|email from me

אלו הן, על קצה המזלג, היכולות של הרחבת ה-FTS של SQLite. ניתן למצוא מידע נוסף בויקי של SQLite

Foreign Keys ב-SQLite

23/01/2008 20:29 ע"י כתריאל טראום

עם העבודה על jiyuu, יוצא לי לא מעט לעבוד עם sqlite. למי שלא מכיר, זה מסד נתונים אשר מיושם בספריה, ללא שרת, ללא צורך בהתקנה ועם תמיכה ב-Transactions.

סכמת מסד הנתונים של jiyuu אינה מסובכת כל כך. היא כוללת כמה טבלאות פשוטות שמחזיקות פוסטים, תגובות, תגיות וקונפיגורציה. אבל, למרות הפשטות, היה חסר לי מאפיין אחד חשוב, שיעזור לי לשמור על הנקיון ועל תקינות המידע: Foreign Keys.

הסבר מהיר: Foreign Keys הוא מנגנון במסדי נתונים שמאפשר יצירת קשר בין טבלאות שונות. בעזרת Foreign Key ניתן לקשר מידע בטבלה א' למידע בטבלה ב' כך שלא יכול להיות מידע בעמודה מקושרת בטבלה א' שאינו קיים בטבלה ב'. קישור זה הוא בד"כ דו-כיווני: לא ניתן יהיה למחוק מידע מטבלה ב', כל עוד ישנם רשומות בטבלה א' שעדיין מפנות אליה.

דוגמא:

CREATE TABLE tbl1 (
	id INTEGER PRIMARY KEY NOT NULL,
	col1 VARCHAR(20),
	col2 INTEGER NOT NULL CONSTRAINT fk_tbl2_id REFERENCES tbl2(id))

זהו התחביר ליצירת Foreign Keys ב-SQLite (אפילו שהוא לא תומך ב-Foreign Keys. עוד על זה מיד). לפי הדוגמא, לא ניתן יהיה להכניס שורה חדשה לטבלה tbl1, במידה והערך של col2 לא יהיה קיים ב-tbl2. בכיוון השני, ברגע שיש מידע שבטבלה tbl1 אשר מקושר ל-tbl2, לא ניתן יהיה למחוק את הרשומה שאליה המידע קשור ב-tbl2.

רק רגע, אבל הרגע אמרתי ש-Foreign Keys לא נתמך ב-SQLite. המצב כרגע הוא שהפקודות קיימות, אך SQLite לא מתייחס אליהם או עושה להם Parsing\Enforcing. אז איך כן ניתן ליישם Foreign Keys שישמרו על אחידות המידע שלי? התשובה פשוטה: Triggers

הפוסט הזה הופך לשעור ב-SQL… אז מה זה Triggers? אלו פקודות SQL אשר מורות למסד הנתונים לבצע פקודה מסויימת כאשר מתרחש מקרה מסויים. ניתן לנצל יכולת זו כדי לתפוס כל מחיקה, יצירה או שינוי של רשומה כדי לוודא שאין התנגשות עם Foreign Key. נצטרך לצור 3 Trigger-ים: אחד עבור יצירה, מחיקה ועדכון רשומה, בעבור כל טבלה שבא הגדרנו Foreign Key Constraint

CREATE TRIGGER fk_insert_tbl1
BEFORE INSERT ON tbl1
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'insert on table "tbl1" violates foreign key constraint "fk_insert_tbl1"')
  WHERE (SELECT id FROM tbl2 WHERE id = NEW.col2) IS NULL;
END;

CREATE TRIGGER fk_update_tbl1
BEFORE UPDATE ON tbl1
FOR EACH ROW BEGIN
    SELECT RAISE(ROLLBACK, 'update on table "tbl1" violates foreign key constraint "fk_update_tbl1"')
      WHERE (SELECT id FROM tbl2 WHERE id = NEW.col2) IS NULL;
END;

CREATE TRIGGER fk_delete_tbl2
BEFORE DELETE ON tbl2
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'delete on table "tbl2" violates foreign key constraint "fk_delete_tbl2"')
  WHERE (SELECT col2 FROM tbl1 WHERE col2 = OLD.id) IS NOT NULL;
END;

הרבה מידע, אני יודע. אבל אם מתעמקים טיפה, לא מסובך מדי. 2 הדוגמאות הראשונות בעצם דואגות כי לפני יצירה\שינוי ב-tbl1, ייבדק כי קיים ערך מתאים ב-tbl2. הדוגמא השלישית פועלת בכלל על tbl2 בזמן מחיקת רשומה, ומוודאת כי אין רשומות מקושרות ב-tbl1. שימו לב כי אם השדה col2 ב-tbl1 לא היה מוגדר כ-NOT NULL, הפלט היה קצת אחר, אם לדוגמא ניקח את ה Insert Trigger הבא:

CREATE TRIGGER fk_insert_tbl1
BEFORE INSERT ON tbl1
FOR EACH ROW BEGIN
  SELECT RAISE(ROLLBACK, 'insert on table "tbl1" violates foreign key constraint "fk_insert_tbl1"')
  WHERE NEW.col2 IS NOT NULL AND (SELECT id FROM tbl2 WHERE id = NEW.col2) IS NULL;
END;

התוספת היא השורה WHERE NEW.col2 IS NOT NULL, אשר מוודא כי השדה החדש אינו ריק לפני שה-Foreign Key נאכף.

למחפשים עוד מידע, את הדוגמאות שלי שאבתי מהקישור הבא, והשתמשתי בכלי הבא כדי לייצר Triggers מה-Foreign Keys שלי.

אז עכשיו יש ל-jiyuu מסד נתונים מסודר, נקי ונכון. וכדי להפוך את הסכמה לקריאה יותר, השארתי את פקודות ב-Foreign Key המקוריות.

טיפ: ssh-copy-id

20/01/2008 20:11 ע"י כתריאל טראום

אז יש לכם כמה שרתים לנהל? אולי כמה עשרות? אתם בטח משתמשים ב- SSH Private/Public key בשביל להזדהות בהתחברות אליהם, זה מה שאני הייתי עושה.

אם זה המצב, סדר הפעולות הבא בודאי לא זר לכם. העתקת המפתח, התחברות למכונה, העברה ל-authorized_keys, מחיקת המפתח. מיגע.

$ scp .ssh/id_dsa.pub 192.168.1.10:~/
Password:
id_dsa.pub            100%  604 0.6KB/s   00:00
$ ssh 192.168.1.10
Password:
.
katriel@server1:~$ cat id_dsa.pub >> .ssh/authorized_keys
katriel@server1:~$ chmod 700 .ssh
katriel@server1:~$ chmod 600 .ssh/authorized_keys
katriel@server1:~$ rm id_dsa.pub
katriel@web-vm:~$ logout
Connection to 192.168.22.107 closed.
$ ssh 192.168.1.10
katriel@server1:~$

אז אל דאגה. לעזרתנו מגיע הכלי ssh-copy-id, שעושה את הנ"ל, בפקודה אחת:

$ ssh-copy-id -i ~/.ssh/id_dsa.pub 192.168.1.10
34
Password:
Now try logging into the machine, with "ssh '192.168.1.10'", and check in:

  .ssh/authorized_keys

to make sure we haven't added extra keys that you weren't expecting.

$ ssh 192.168.1.10

katriel@server1:~$

קצר ולעניין, אני לא חשוב שיש צורך בהסברים מיותרים. תהנו!

RPM גירסא 5

10/01/2008 20:48 ע"י כתריאל טראום

אחרי ההצהרה הראשונה על מפת דרכים ל-RPM5, שוחרה לאחרונה הגירסא הסופית. RPM5 הוא גירסא חדשה של RPM הותיק שקיים כבר מאז 1997. RPM התחיל את דרכו כ-Red Hat Package Manager, אבל כיום, הוא ראשי תיבות רקורסיביים: RPM Package Manager, כמו שכל כך אהוב אצלנו בעולם הקוד הפתוח.
גירסא 5 כוללת שיפורים כמו שכתוב קוד המקור לתמיכה בעוד מערכות הפעלה: Soalris, BSD ו-MacOSX, כל אלו כמובן, בתוספת לסביבה הטבעית שלו, לינוקס. מפתחי גירסא 5 טוענים לשיפור ביצועים; פעולות התקנה ושאילתות אמורות להיות פי-10 מהירות יותר. קבצי ה-SPEC שופרו, וכוללים היום אופציה להורדה של קבצי המקור בזמן בניית ה-RPM ועוד. תמיכה ב-RPMv3 הוסרה, מה שמוריד סיבוכיות וכמות קוד מהפרויקט.

כל זה נשמע מצויין, אבל אליה וקוץ בה, RPM5, כך טוענת רד-האט, היא בעצם Fork של RPM בגירסא 4, שלטענת רד-האט והפצ(צ)ות אחרות אשר משתמשות ב-RPM, היא הגירסא הרשמית. בנוסף, אומרת רד-האט, כי אין בכוונתה או בכוונת פרויקט פדורה לעבור להשתמש בגירסא 5 של RPM.

שני האתרים טוענים כי הם ה"גירסא הרשמית" של ה-RPM Code base, אבל יותר נכון הוא ש-RPM5 מבוסס על RPM4. המפתחים של RPM5 טוענים כי הם מקפידים לשמור על תאימות מלאה עם RPM4, ואף מכניסים קוד ותיקונים מ-RPM4 לגירסא 5.

אז מי הרשמי? מי המתחזה? סביר להניח, שכמו תמיד, מבוסס פה כל הסיפור על יוקרה ויריבות. את RPM4 מפתחת רד-האט בעיקר, בשיתוף עם שאר ההפצות מבוססות RPM כמו סוסה ומנדריבה. את RPM5 מנהיג אחד המפתחים לשעבר של RPM4 אשר עבד ברד-האט והיה חלק מפיתוחו של RPM4. את המסכנות תסיקו לבד.

אישית, אני מקווה שרד-האט ושות' כן ישקלו לאמץ את RPM5, או לפחות חלק מה-features שלו. אחרי קצת משחקים ונסיונות, הוא אכן מרגיש הרבה יותר חלק ומהיר. עוד לא התעמקתי בקבצי ה-SPEC המחודשים, אבל בהחלט נראה שיש התקדמות.
במיוחד קורצת לי התמיכה בריבוי פלטפורמות. לאחר נסיון עבר בכתיבת חבילות (למזלי החבילות ארזו אך ורק סקריפטים) לרד-האט וסולאריס, אני יכול להגיד שזו לא חויה מרנינה במיוחד.

Tracker כתחליף ל-Beagle

16/12/2007 21:43 ע"י כתריאל טראום

אני מניח שאני לא מחדש הרבה לרוב משתמשי אובונטו (אם בכלל שמתם לב), אבל גם ל-Fedora נוסף בגירסא האחרונה (אולי אפילו בגירסא 7, לא ניסיתי אותה) מנוע מיפתוח (Indexing) למידע אישי בשם Tracker, או בעברית, "הגשש". בניגוד לחברו הכלב (Beagle), הוא כתוב ב-C והרבה יותר קל מבחינת שימוש בזיכרון וניצול CPU.

אז שיחררתי את הגשש על המידע האישי שלי, ובאמת, תוך פחות מ-5 דקות הוא כבר מיפתח את כל המידע שלי, ואת החשבון imap שמקושר ל-gmail. בצורה זו יש לי את כל המידע, כולל אימיילים, בנקודת חיפוש אחת.

Tracker משתמש ב-sqlite כדי לאחסן את המידע, מה שהופך את כל תהליך השליפה למהיר מאין כמותו:

$ time tracker-search penguin | wc -l
90

real    0m0.024s
user    0m0.000s
sys     0m0.000s

אם זה לא היה ברור, זה 90 תוצאות בחמישית השניה.
ברוח ה-Web 2.0, הגשש מאפשר גם לשייך תגיות לקבצים, ספריות וכל דבר אחד שיודע הגשש למפתח. אפשרות זו מאפשרת חיפוש נוח יותר לפעמים, כאשר לא ממש זוכרים את שם המסמך או תוכנו, אלא נושא כללי שאליו מתייחס המסמך. האקר זריז אף כתב פלאגין זריז ל-Nautilus אשר מאפשר תיוג דרך Nautilus. כמובן שהגשש יודע גם ליצור Thumbnails לרוב סוגי הקבצים שהוא יודע למפתח.

מה אפשר להגיד, את הכלב זנחתי, הגשש הוא הממפתח (Indexer) החדש שלי.

לינוקס להמונים

17/09/2007 18:58 ע"י כתריאל טראום

במאמר די מקיף (גם אם לא הכי מדוייק לטעמי), סוקרת אדר שלו ב-YNET את הסיבות מדוע לדעתה לינוקס כיום לא מוכנה לשולחן העבודה.

למרות נימה חיובית כלפי לינוקס, עם כמה הצהרות גורפות כמו "רוב המשתמשים לא ממהרים לעבור אליה, וגם חלק ניכר מאלה שעוברים אליה נוטשים אותה" או "בלינוקס חיבור ברירת המחדל כמנהל אינו מקובל בכלל, על אף שחלק מהמשתמשים התמרדו נגד ההגבלה הזו", אני חושב שהכתבה מציגה באופן די שקול את העיניין.

בעוד היא מציגה את לינוקס כמערכת הפעלה שקשה יהיה למשתמש הממוצע להתרגל אליה אחרי "חיים שלמים" בחלונות. בכתבה היא מפרטת מעט על החוויות שלה עם לינוקס, חוויות אלו כוללות דברים כמו קימפול קרנל חדש בשביל תמיכה בכרטיס קול, ומבטיחה אתגר ועיניין למי שיחליט בכל זאת לנסות את לינוקס.

אני חייב להגיד שבכל פעם שאני קורא כתבה על לינוקס מוכנה\לא מוכנה למשתמש הביתי, זה נראה לי קצת דיון טפל. טענתי, ואני ממשיך לטעון כי לינוקס ויוניקס זה בשביל שרתים. אין כמו היציבות, אין כמו הגמישות והחוזק של מערכת הפעלה יוניקסית. שולחן העבודה לינוקסאי? צעצוע נחמד בנתיים, לא לכל אחד.

בתור אחד המגדיר עצמו Power User, אני נהנה מהאתגר והעיניין כמו שהגדירה את זה אדר שלו, שיש בשימוש בלינוקס. אבל זה עדיין, בהחלט, לא לכל אחד.

העתיד בנושא זה, אני חושב הוא דווקא מאותם אנשים שעדיין לא "קולקלו" ע"י חלונות, ויתחילו דרכם בלינוקס. הם אלו שבסוף יהפכו אותה למשהו שמיש באמת למשתמש הביתי הפשוט.

הרפתקאות עם lguest

31/08/2007 18:17 ע"י כתריאל טראום

כבר זמן מה אני מדבר על lguest ועל הרצון שלי לנסות אותו קצת. הפוסט הבא הוא קיצור נסיוני עם lguest.

למי שלא מכיר, למי שלא שמע, lguest הוא פתרון וירטואליזצה קליל ("רק" 5000 שורות קוד) שכתב ראסטי ראסל (Rusty Russell) ומוזג עם קרנל 2.6.23 לראשונה.

lguest מגיע כמודול (אם רוצים) וכלי userland פשוט לניהול ה-VM-ים אשר יושב בספריית lguest תחת Documentation בעץ הקרנל. קימפול הכלי הוא די פשוט ומוסבר בדוקומנטציה. לפני שתתחילו לעבוד עם lguest, קמפלו אותו.

בהמשך להשוואה שערכתי בפוסט קודם, אציין רק שהחוזק העיקרי של lguest הוא הפשטות וה"קלות" שלו לעומת פתרונות אחרים. הוא משתמש באותו הקרנל בעבור מחשב אורח ומארח, ומדובר רק במודול ולא ארכיטקטורה שלמה.
החסרון העיקרי שלו לעומת המתחרים הוא חוסר תמיכה במערכות אחרות מלינוקס. אישית הנושא של חוסר תמיכה במערכות שאינן לינוקס אינו מפריע. גם כך אינני עובד איתם בבית ביום יום. (למרות שיש לי XP (חוקי, כן, כן, חוקי למהדרין) ב-Dual Boot בשביל הבנק ופתרון VPN שלא נתמך בלינוקס, לכו תבינו).

לפני שמתחילים לעבוד עם lguest, להלן רשימת נושאים שכדאי לדעת לפני. למזלכם, כבר השקעתי את הזמן כדי לפתור את הבעיות עד שעלתה לי מערכת:

  • lguest עדיין לא מגיע עם הפצות נפוצות כרגע, מכיוון שהוא הוכנס כ-Patch רק בגירסא 2.6.23-rc1. מה שאומר בעצם שכרגע, צריך לקמפל קרנל בשביל תמיכה ב-lguest. לא להיט, אבל לא נורא אם יש קצת סבלנות. הערכים שיש לדאוג לאפשר הם:
  CONFIG_HIGHMEM64G=n ("High Memory Support" "64GB")[1]
  CONFIG_TUN=y/m ("Universal TUN/TAP device driver support")
  CONFIG_EXPERIMENTAL=y ("Prompt for development and/or incomplete code/drivers")
  CONFIG_PARAVIRT=y ("Paravirtualization support (EXPERIMENTAL)")
  CONFIG_LGUEST=y/m ("Linux hypervisor example code") 

הערה: CONFIG_LGUEST נמצא תחת Device Drivers

  • ה-console device של מערכת שרצה תחת lguest הוא /dev/hvc0, צריך להוסיף שורה בסגנון של:
1:2345:respawn:/sbin/getty hvc0

לקובץ /etc/inittab של ה-image שבו תשתמשו. ולא לשכוח, כדי ש-root יכול לעשות דרכו לוגין, צריך להוסיף אותו ל-/etc/securetty

  • lguest משתמש ב-tunnel device כדי לתקשר עם מערכת ההפעלה המארחת. דרך אחת היא להשתמש ברשת פרטית ו-NAT כדי לאפשר ל-VM לצאת לעולם, אך הדרך שמצאתי נוחה יותר היא בעזרת Bridge. בפדורה, כדי לקנפג Bridge Interface יש לצור קובץ ifcfg-lg0 שהוא בעצם Bridge ולקשר אליו את eth0.

אצלי זה נראה כך:

  • הקובץ /etc/sysconfig/network-scripts/ifcfg-lg0:
DEVICE=lg0
BOOTPROTO=static
BROADCAST=192.168.1.255
IPADDR=192.168.1.10
NETMASK=255.255.255.0
NETWORK=192.168.1.0
ONBOOT=yes
  • והקובץ /etc/sysconfig/network-scripts/ifcfg-eth0:
DEVICE=eth0
BOOTPROTO=static
ONBOOT=yes
BRIDGE=lg0

יותר מאוחר כאשר נצור את ה-VM, נקשר אותו ל-Bridge הנ"ל.

  • הדיסקים של המערכת האורחת נקראים lgba, lgbb וכו'. הייתי צריך לעדכן את ה-fstab של המערכת האורחת כדי שתתאים לשמות החדשים. בנוסף צריך לעשות אחד משני הדברים הבאים כדי שהמערכת תכיר את ה-block devices:
    • לדאוג שלמערכת האורחת יש udev
    • לצור אותם עם mknod. ה-major של lgba הוא 253 ושל lgbb הוא 252. השיטה העדיפה היא כמובן udev.

טוב, אני חושב שזה כל ה-gotchas שצריך לשים לב אליהם. אפשר להתחיל לעבוד.
אני השתמשי ב-image של דביאן בגירסא 3.1 שהורדתי מ-jailtime.org, ושידרגתי בעזרת apt לגירסה 4.
שימו לב : כדי לחסוך בזמן הורדה/מקום, jailtime מספקים rootfs בגודל של 1G בלבד. ניתן לעקוב אחרי ההוראות הבאות כדי להגדיל אותו.

אחרי שהורדתי, פרסתי, מחקתי את המיותר ושיניתי שמות למשהו הגיוני יותר נותרתי עם הקבצים הבאים:

  • root-lgba.img
  • swap-lgbb.img

שלב הבא היה סידור ה-rootfs כדי שיעבוד עם lguest. עיגנתי את root-lgba.img וביצעתי chroot לתוכו. ערכתי את fstab, inittab, securetty והתקנתי udev בשביל יצירה אוטומאטית של devices. זהו, מוכנים להפעיל את lguest כבר?
רק עוד נקודה אחרונה. אין ל-lguest עדיין ניהול קונסול מבריק או יכולות daemon. הכלי lguest (כבר קימפלתם אותו נכון?) מורץ משורת הפקודה, ואם תסגרו את הטרמינל או תריצו pkill lguest, ה-VM שלכם ימות באכזריות. לצורך כך השתמשתי ב-screen כדי להריץ את ה-vm ולשמור לי את היכולת להתנתק ממנו בעת הצורך כדי שלא יתפוס לי טרמינל.

יאללה, לעבודה, הכל מוכן. הפקודה להרצת ה-vm נראית כך:

# screen
# lguest 128m /boot/vmlinux-2.6.23-rc5-lguest --tunnet=bridge:lg0 \
--block=/home/data/vm/web-vm/root-lgba.img \
--block=/home/data/vm/web-vm/swap-lgbb.img root="/dev/lgba ro"

שימו לב שאני משתמש ב vmlinux (שעשיתי לו strip) ולא vmlinuz. לפי הדוקומנטציה ניתן להשתמש ב vmlinuz אך בנסיונות שלי זה לא עבד. אם הכל עבר כשורה, יש לכם כעת VM רץ לשימושכם.

אישית אני משתמש ב-lguest כ-vm לפיתוח של jiyuu. שימושי.

פוטו רצח

31/08/2007 11:47 ע"י כתריאל טראום

ליאור קפלן סוף סוף העלה את תמונות הפוטו רצח שלו מאוגוסט פינגווין. לצערי השנה לא יכולתי להגיע, אבל שמחתי לראות וסוף סוף לקשר כמה פרצופים לכמה שמות שיוצא לי לעבוד איתם לפעמים בקהילה.

השנה אוגוסט פינגווין קצת שונה מבחינתי. עם המרחק והמשפחה, לא היה לי ממש זמן להגיע. בכלל, בשנה שחלפה שאני מרגיש שאני לא תורם ועושה כמו שהייתי רוצה בקהילת הלינוקס הקטנה שלנו. נקווה שבשנה הבאה עלינו לטובה המצב ישתפר קצת.

מי מפחד מהחושך? (ומ-Sendmail ו-LDAP?)

18/07/2007 19:51 ע"י כתריאל טראום

שנים רבות שפחדתי מ-Sendmail, באמת. הסתכלתם פעם בקובץ קונפיגורציה שלו? אם אתם אמיצים, פתחו את הקובץ sendmail.cf (משאיר לכם כתרגיל למצוא את המיקום שלו), וראו אם אתם מצליחים להבין איזה כמה שורות קונפיגורציה שם. לא, הא? טוב, אתם לא לבד, 99.999% מאוכלוסיית העולם אינה מסוגלת לקרוא את הקובץ. אבל אל דאגה, לעזרתנו באה שפת המאקרואים m4, למי שלא מכיר, תגידו שלום ל-sendmail.mc, מכיל רק כמה שורות, קצת יותר נהירות, שבעזרתם בונה המפענח (m4) את sendmail.cf.

יופי, עכשיו שהבהרנו את הנושא הזה, בוא ונסתכל על אחד מהמאפיינים של Sendmail שעושה אותו כלי מצויין (למרות שכיום, חביב עלי יותר postfix), מפות. לא, לא מפות שולחן, אלא שימוש בקבצי מיפוי כדי להכניס גמישות ושליטה של מנהל הרשת על Sendmail מחוץ ל-sendmail.cf. לדוגמא, Sendmail מאפשר לנתב דואר נכנס לשרת אחר, או דואר מאימייל אחד למשתמש אחר.

הכל טוב ויפה כאשר יש שרת אחד לנהל. מה קורה כאשר יש 10? 20? (קיימות מערכות כאלו ואף גדולות יותר) אנחנו צריכים מקום מרכזי שיחזיק את כל המידע הזה בצורה מרוכזת, כדי שדואר אשר נכנס בכל אחד מהשרתים יקבל את אותו "הטיפול". להצלתנו מגיע כמובן LDAP הפרוטוקול ו-OpenLDAP השרת.

למי שחי מתחת לאדמה בשנים האחרונות ולא שם לב, LDAP הפך להיות ה"סכין צבאית שוויצרית" (Swiss Army Knife, נשמע יותר טוב באנגלית, תודו) של אנשי ה-IT. אם פעם היה מחזיק רק משתמשים או כתובות, היום הוא כבר "יודע" להחזיק מידע כמו מפות של Sendmail/Postfix, מידע DNS-י, משתמשים, קבוצות, automounts ומה לא… במקרה שלנו, נרתם שרת ה-LDAP כדי להחזיק מפות של Sendmail. לא רע בכלל בשביל פרוטוקול צעיר (יחסית, בערך מ-1993).
LDAP (או Light Weight Directory Access) תוכנן כפרוטוקול שנועד להחזיק מידע היררכי בצורה יעילה ומהירה לגישה, וזה בדיוק מה שהוא עושה פה בעבור Sendmail.

על הנושא של התקנת, קינפוג ותחזוקת שרת OpenLDAP לא אדבר, כי הוא חורג מגבולות הבלוג הזה שמטרתו: שירת הלל ל-LDAP. בכל מקרה, אז איך אנו גורמים ל-Sendmail לדבר עם שרת LDAP? ואיך אנו גורמים לו לשאול את השאלות הנכונות? בואו ואספר לכם.

בתור התחלה, נצטרך להגיד לשרת ה-LDAP כיצד לבנות רשומות שיבין Sendmail, איך עושים את זה? במילה אחת - sendmail.schema. סכמה היא קובץ המגדיר סוגי אוביקטים, סוג המידע שבכל אוביקט ואת היחס ביניהם. ניתן למצוא את הסכמה בקבצי המקור של Sendmail או ברוב ההפצות כיום. את הסכמה יש לשים בספריית הסכמות של OpenLDAP (בד"כ /etc/openldap/schema) ולהוסיפה לקובץ הקונפיגורציה של OpenLDAP:

include         /etc/openldap/schema/core.schema
include         /etc/openldap/schema/cosine.schema
include         /etc/openldap/schema/inetorgperson.schema
include         /etc/openldap/schema/nis.schema
include         /etc/openldap/schema/sendmail.schema

שלב הבא במסענו לארץ LDAP, יהיה יצירת המפות כדי ש-Sendmail יוכל לגשת אליהם, ניצור את ה-DN הבסיסי ומתחתיו את המיפויים. בדוגמא הבאה ניצור מפה מסוג virtusertable:

# cat > ldap-virtuser 
dn: sendmailMTAMapName=virtuser, dc=example, dc=com
objectClass: sendmailMTA
objectClass: sendmailMTAMap
sendmailMTACluster: example.com
sendmailMTAMapName: virtuser

dn: sendmailMTAKey=user@example.com, sendmailMTAMapName=virtuser, dc=example, dc=com
objectClass: sendmailMTA
objectClass: sendmailMTAMap
objectClass: sendmailMTAMapObject
sendmailMTAMapName: virtuser
sendmailMTACluster: example.com
sendmailMTAKey: user@example.com
sendmailMTAMapValue: user-example

כדי להוסיף את המפה נצטרך להשתמש בכלי ldapadd של OpenLDAP:

# ldapadd -D cn=manager,dc=example,dc=com -b dc=example,dc=com -W -x < ldap-virtuser

מצויין! יש לנו רשומה בשרת ה-LDAP שממפה את user@example.com למשתמש user-example.

שלב אחרון במזימה שלנו הוא קינפוג Sendmail שידע לחפש בשרת ה-LDAP, על מנת לעשות זאת, נצטרך להכניס כמה שינויים ותוספות ב-sendmail.mc חפשו את השורה

FEATURE(`virtusertable',`hash -o /etc/mail/virtusertable.db')dnl

והחליפו אותה בשורות הבאות:

define(`confLDAP_DEFAULT_SPEC', ` -h ldserver -b dc=example,dc=com')
define(`confLDAP_CLUSTER', `examplecom')
FEATURE(`virtusertable', `LDAP')

הערה: עוד מידע על האפשרויות של confLDAP_DEFAULT_SPEC בכתובת הבאה

כדי לצור sendmail.cf חדש, נשתמש במפענח m4:

m4 sendmail.mc > sendmai..cf

זהו, פשוט לא? אתחול זריז ל-Sendmail ואנחנו מוכנים לבדוק אם הכל עובד כמו שאנו מקווים. נבצע בדיקת מיפוי, ונראה שאכן המשתמש ממופה כמו שצריך:

# sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
> /map virtuser user@example.com
map_lookup: virtuser (user@example.com) returns user-example (0)

מושלם! ביקשנו מ-Sendmail לפענח בעבורנו, מתוך המפה virtuser לאיזה משתמש מופנה הדואר בעבור הכתובת user@example.com, והתשובה הנכונה לא אחרה להגיע לאחר שאילתה קטנה לשרת ה-LDAP

אז נכון, Sendmail הוא יצור מאיים, LDAP הוא פרוטוקול שנראה מסובך, אבל השילוב בין השתיים יכול להביא לניהול נוח וגמיש בהרבה של שרתי Sendmail. תודו שאתם מופתעים מכמה שזה היה פשוט.

שרת במשקל נוצה

18/07/2007 19:50 ע"י כתריאל טראום

אני לא אוהב דברים מנופחים, באמת שלא. לא אוהב מחשבים מגודלים, אפליקציות מפלצתיותת, מערכות הפעלה מסובכות… לראיה, המחשב האהוב עלי בבית הוא ה-NSLU2 שלי שמריץ דביאן ומשמש בתור פיירוול\VPN\חייגן.

אם כך, זה לא פלא שכאשר גיליתי את Lighttpd התאהבתי ישר. "על מה הוא מדבר לעזאזל?" אתם בטח חושבים לכם. ובכן, lighttpd הוא חלופה קלה, מהירה וגמישה ל-Apache המוכר (ולפעמים מנופח). כמה מהתכונות של lighty (קיצור של lighttpd) שגרמו לי להתאהב הם:

  • שרת חד-נימי (Single-Threaded), מה שאומר שהוא משתמש בכמות זכרון נמוכה
  • בר הרחבה בעזרת מודולים (כמו rewrite, fastcgi, cgi, vhosts ועוד)
  • בנוי בעבור סביבות עתירות עומסים, עם אופציות שיפצור תואמות (שימוש ב-sendfile ועוד)

Lighty, אשר נכתב על ידי יאן קנשקה (Jan Kneschke) אי שם בשנת 2003, נכתב בכלל כהסחת דעת מכתיבת תעוד (שהוא מעיד עליו כחלק השנוא על כל מפתח, נשמע מוכר) לתיזה שלו. הוא התחיל את הפרויקט כנסיון לפתור את בעיית "10000 החיבורים לשרת" (C10K של דן קגל), ועד מהרה הגיע לשרת עם ביצועים מצויינים שהופך יותר ויותר פופולארי.

אז פעם הבאה שאתם שוקלים להקים שרת LAMP, אני מציע שתשקלו את החלופה הקלילה יותר, הקמת שרת LLMP

לאמן את הכלב

18/07/2007 19:45 ע"י כתריאל טראום

את מנוע החיפוש beagle לא צריך להציג, הוא מן הסתם החלופה הראויה ביותר ל-Google Desktop בעבור סביבת לינוקס. חלק מתכונותיו השימושיות כוללות עדכון בזמן אמת של תוצאות החיפוש, אינדוקס מיידי של דואר נכנס, שיחות ב-Instant Messenger וקבצים חדשים, יכולת אינדוקס של מגוון רחב של פורמטים ומקורות מידע ועוד.

Beagle נשען על מנוע האינדוקס המצויין Lucene מבית פרויקט Apache שהומר לשפת .Net

לאחרונה הוספתי דיסק קשיח נוסף למחשב אשר החזיק מסמכים, מוזיקה וסרטים ממערכת ישנה שלי. כיוון שהתנהגות ברירת המחדל של Beagle היא לאנדקס רק תוכן מתוך ספריית הבית, פתחתי את ממשק הקונפיגורציה שלו, והוספתי ספריה נוספת לאינדוקס:

לספריה /home/data/mm עיגנתי את הדיסק הנוסף. ברגע שנוסף ל-Beagle ספריה נוספת, הוא מתחיל ישר לסרוק אותה ולאנדקס את כל החומר החדש. הבעיה התחילה כאשר לקח לו יותר מדי זמן, ורציתי להתחיל למצוא מסמכים ושירים בצורה די מיידית (חיברתי את הדיסק כדי למצוא מסמך מסויים). הפתרון נמצא בדמות משתנה סביבה (Environment Variable), שכאשר הוא מועבר ל-Beagle, מורה לו להתחיל לסרוק בצורה נמרצת. התהליך הוא:

$ beagle-shutdown
$ export BEAGLE_EXERCISE_THE_DOG=1
$ beagled

אם בד"כ Beagle מנסה לגזול כמה שפחות משאבי מעבד וזכרון כדי לא להפריע לריצה נורמאלית, אז משתנה זה אומר לו לעשות הכל ולהשתמש בכל משאב שהוא רוצה כדי להתחיל ולסרוק שינויים ואוביקטים חדשים. אכן, תוך 15 דקות כבר היה הדיסק הקשיח החדש סרוק ומאונדקס כולו.

ומה איתי? בזמן שהכלבלב סרק, אני יצאתי בנתיים להפסקת קפה.

מחיקת תור ההודעות של Postfix

18/07/2007 19:43 ע"י כתריאל טראום

לאחרונה יצא לי לשדרג את מערכת ההפעלה של הפינגווין מפדורה בגירסא 5 ל-CentOS 5. אני מקווה שהצעד הזה ישאיר את המערכת מעודכנת ומאובטחת יותר לאורך זמן (פדורה 5 כבר אוטוטו עוברת ל-Legacy). בתהליך השדרוג, שכחתי לכוון את שרת הדואר של הפינגווין שיצא דרך ה-Mail Relay שלנו. כתוצאה מכך נתקעו לי לא מעט מיילים יוצאים בשרת הדואר הפנימי.
חשבתי כבר הנה שוב אצטרך לכתוב איזה שורת פקודה ארוכה ומסובכת כדי לרוקן את התור היוצא (כמו שאני בד"כ עושה עם סנדמייל שמחזיק מיילים לא רצויים). להפתעתי ושימחתי, גיליתי כלי ל-Postfix יש כלי לניהול התור שמסוגל לעשות זאת בשבילי. פקודה אחת קצרה ולעניין פתרה את כל הבעיה:

sudo postsuper -d ALL

פקודה זו תרוקן את כל התורים של Postfix: נכנס, יוצא ו-Deffered. ניתן למחוק בצורה סלקטיבית יותר, כמו תמיד man 1 postsuper יספק יותר מידע מבלוג זה.