קטגוריה: לינוקס

יצירה וטעינה של ספרייה משותפת בגו

גו היא שפת תכנות מהודרת, אשר יוצרת קבצי ריצה טבעיים של מערכת ההפעלה. מאז גרסה 1.5, נכנסה האפשרות ליצור ספרייה משותפת דינמית (DSO). בגרסה 1.5, התמיכה הייתה ניסיונית, ובגרסה של 1.6, התמיכה נכנסה כתמיכה רשמית של המהדר.

מה זו בעצם ספרייה משותפת?
בקצרה, על רגל אחת, ספרייה משותפת זהו קובץ "ריצה" (למשל בפורמט PE בווינדוז או ELF ביוניקס), אשר אינו מחזיק בחלק ריצה כפרוסס (לרוב נקרא main).
לקובץ הריצה יש רשימה של פונקציות אשר "מיוצאות", כלומר הכתובות שלהם נגישות כלפי חוץ כאשר רוצים להשתמש באותן הפונקציות.
השמות של אותן הפונקציות נקראות symbols והגישה אליהן מתרחשת על ידי כתובות זיכרון.
במידה ופרוסס מסויים מקשר אליהן בצורה סטטית, כלומר בזמן הידור, יודעים את המיקום שלו ביחס לשאר הפונקציות של הפרוסס, כאילו היה חלק מהפרוסס עצמו.
כאשר הטעינה מתבצעת בזמן ריצה, יש אתחול זיכרון דינאמי אשר מחזיק את הכתובת.

כיצד יוצרים ספרייה משותפת בגו? להמשיך לקרוא

מימוש RDP טבעי בשפת רובי

על רגל אחת, RDP הם ראשי תיבות של Remote Desktop Protocol. אך השם מעט מטעה. זוהי למעשה אסופה של הרבה מאוד פרוטוקולים, חלקם אפילו לא של מיקרוסופט, אלא של ארגון ITU. למעשה הוא מבוסס על סדרה של פרוטוקולים שהחלו את דרכם בארגון ה ITU אשר נועדו לאפשר לתוכנות לשתף מידע ותכנים בניהם.

הפרוטוקולים עצמם הם פרוטוקולים בינאריים, ולא פרוטוקולים טקסטואליים (כדוגמת HTTP למשל), וככאלו יש עבודה רבה עם bit manipulation והבנה של מיקומים שונים ומה המשמעות שלהם.
הרעיון של RDP הוא להצליח להעביר את כל סביבת המיקרוסופט למחשב מרוחק, כולל העתקת קבצים, שיתוף מדפסות, שיתוף כוננים, שיתוף קול ואפילו לבצע הזרמה של ווידאו.

כל זה נעשה תחת מערכת שמבצעת הזדהות מול מערכת כדוגמת Active Directory בפרוטוקולים כדוגמת NTLM ו spnego, אשר האחרון, הוא מימוש הזדהות התומך גם בקרברוס למשל, כאשר התעבורה אמורה להיות מוצפנת בגישות שונות, בהתאם לתמיכה של שני הצדדים. על כל זה מופעל סוג של compression למידע.

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

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

כתובת הפרויקט: https://github.com/Safe-T/rdp-rb

ניסויים בתורי הודעות

יש מערכת שאחרי load test הבנתי כי אני חייב לבזר את המערכות שבה. אז התחלתי לבצע מחקר על סוגים שונים של message queue בשביל לבזר את המערכת. עשיתי ניסויים עם המון מערכות שונות, כולל התייעצות עם אנשים שממשים כבר מערכות המשתמשות בהם, והגעתי להבנה כי כנראה ש RabbitMQ מתאים לצרכים שלי.

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

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

למשל אני עשיתי 2 הגדרות בלבד לRabbit להתאים למכונת הפיתוח החלשה שלי, והגעתי ללמעלה מ7 מליון בקשות בשניה אחת, עד שרוחב הפס נחנק, אבל ה load היה על 0.02 לאורך זמן רב. כלומר לא הגעתי ל load שהם דיברו עליו. אבל יכולתי לבדוק לאורך זמן, רק כאשר ירדתי בערך ל5 מליון בקשות בשניה, ואז הרוחב פס כבר לא נחנק לי.

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

יותר מזה, בתיעוד של Rabbit, כתוב שאפשר להגביל את ה load על המכונה, במידה ועוברים כמות מסויימת של שימוש במשאבים, היא מפסיקה לקבל עבודות, דבר שגם לא הוסבר אם נכנס לבדיקה שלהם, אך אני בכלל לא הגדרתי אותו.

כך שלי חסר מאוד מידע איך ומה בוצע בפוסט, אבל אני לא מצליח לשחזר את מה שהם כן מזכירים.
העניין הוא, שאני לא בוטח ברדיס לפעולות ה mq שאני צריך, כי אני צריך מחסנית יציבה של worker..
אם חלילה וחס הוא נפל, אסור שהמידע יאבד, ויותר מזה, במידה ואני צריך להוסיף workers, אני צריך מצב של ביזור המידע, בלי שworker אחד ידרוך על השני, ואני מקבל את זה בצורה טבעית ב Rabbit, (ועוד מספר סוגים של MQ שבדקתי), אבל רדיס מעולם לא תוכנן לזה. הוא נמצא בזיכרון, אני כמובן שיכול להכריח אותו לכתוב לדיסק (איטי מאוד, אבל זה מה שקורה עם persistence queue בRabbit), אבל בשביל לעשות תורים בגישה של Round Robin, ובכן, בלי לכתוב משהו ב lua, אני לא מכיר תמיכה לזה ברדיס, למרות שאשמח לגלות שיש.

ככול שאני עובד כרגע (אמנם עדיין בפיתוח) עם MQ, ככה אני אוהב יותר את הרעיון של השימוש ב Rabbit.
במערכת שאני בונה, יש לי מערכת חיצונית שהיא של ספק אחר שמדברת עם HorentQ, דרך הפרוטוקול שנקרא STOMP (בניגוד לRabbit שברירת המחדל שלו היא AMQP אך תומך גם ב STOMP), והיתרונות של מערכת כזו שהיא robust מאוד, מאפשרת להתמודד עם בעיות שונות, כדוגמת קריסת מערכת, ניתוק התקשורת, התנהלות של load balance של מספר שרתים וכיוב'…

כך שלדעתי, אחרי הרבה ניסויים, אני חושב שRabbit זו הגישה המתאימה לי, ובמידה ולא, תמיד אפשר לעבור בלי להחליף קוד 🙂

 

 

סינטרה מודולרית

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

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

הרעיון שלי הוא למעשה שרת אשר משמש לקוח בדיקות עבור REST, כך שאפשר להתקין אותו על שרת כלשהו בארגון וכולם יכולים להשתמש בו, במקום תוכנה מקומית על המחשב.

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

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

אנחנו משתמשים בRack בעצם, היות וכמעט וכל הframeworks עבור בניית מערכות web ברובי משתמשים בו, אנו זקוקים לקובץ קבוע בשם config.ru.

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

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

לאחר טעינת התלויות, אני טוען קובץ בודד בשם app.rb שהוא בעצם מה שמנהל את האפליקציה שלי. אך במקום להשתמש ב require "רגיל", אני משתמש בפונקציה בשם require_relative, אשר מאפשרת לטעון דברים מהמיקום הנוכחי של הקובץ המנסה לטעון אותה.

כל הקסם של ניהול מספר מחלקות, נעוץ אצלי ב app.rb.
אני יצרתי אותו שיהיה מאוד פשוט – טען לי את המחלקות האחרון והכנס אותן לסביבת העבודה של רובי, על ידי שימוש ב use.

למערכת שיצרתי ישנם שני מצבים – מערכת לדיבוג REST, ומערכת "בדיקות" אשר עליה אפשר לבדוק שדברים עובדים, והיא בעיקר על תקן "echo" כלשהו.

את המערכת של יצירת המסכים, ושליחת ה REST, יצרתי בקובץ rest.rb, והכל מאוגד שם.
יש שם משהו שהולך לעבור למקום אחר בקרוב, וזה מספר מתודות לסיוע בפעולות.

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

Sinatra תומך במשהו אשר קיבל את השם Helpers, וזה מתודות אשר מסייעות לנו לבצע דברים, בצורה שלא נהיה צריכים לחזור עליה כל פעם, וזה זמין גם ל view שלנו, ובגרסה הבאה שאשחרר (נכון לכתיבת הפוסט), המידע יעבור לקובץ בשם helpers.rb ואיתו עובדים קצת שונה ברובי.

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

במקרה הזה, הגדרתי כי במצב של ‎:development משתמשים ב Sinatra::Reloader, אשר מגיע עם Sinatra-Contrib – תת פרוייקט המספק הרבה כלי עזר לדברים שונים.
הסיבה לשימוש ב Reloader הוא לא לאתחל את השרת בכל שינוי שעושים למחלקה של סינטרה, כאשר Reloader מגלה כי התוכן של הקובץ השתנה, הוא גורם ל rack לטעון אותו שוב, וככה אנחנו לא זקוקים לטעינה מחודשת של השרת עצמו.

המערכת שכתבתי, משתמשת ב template בשם haml, למעשה פעם ראשונה אשר אני משתמש בה מרצון. תוכלו למצוא את ה layout.haml שהוא המסגרת הרגילה וכן כרגע קובץ בשם index.haml תחת ספריית view.
ועבור העיצוב, אני משתמש ב Foundation 5, אשר אני אוהב אותה יותר מאשר bootstrap.
עבור Javascript יש גם את jQuery וגם את knockout.js, כאשר אני נעזר גם ב lodash.js למספר דברים פשוטים, והיא מספקת בעצם גרסה שעברה אופטימיזציה ל underscore.

את הקבצים של Foundation, וכל ה Javascript ניתן למצוא תחת public.

דבר אחרון שנשאר לספר עליו הוא שאני משתמש במשהו אשר נקרא puma.
מה זה ?
puma הוא משהו שלוקח את rack וגורם לו להיות שרת לכל דבר ועניין, אשר ניתן לבצע עליו חיבור לשרתי HTTP שונים, כדוגמץ apache או nginx.
החיבור נעשה על ידי הגדרת proxy בשרתים.

ההגדרות של puma, נמצאות תחת config, וכפי שניתן לראות את הקובץ הראשי והחשוב, הוא גם יודע לבנות לעצמו מבנה ספריות במידה והן לא קיימות, דבר שהוספתי לקוד עצמו. הוא כרגע מכוון למצב של development, ולכן יש לשנות קצת הגדרות בשביל שזה יעבור למצב production.

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

האקינג לראוטר, או איך להפוך ראוטר לקוד פתוח

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

מאז לא היו לי אתגרים באמת מעניינים בנושא ההאקינג של מכשירים, עד שרכשתי את WDR4300 של TP-Link והחלטתי שאני לא אוהב את הרעיון שאין לי שליטה על הראוטר שלי.

גיליתי שאני מוגבל, היות ובמדינת ישראל יש הגבלת תדרים על ידי משרד הביטחון (ולא משרד התקשורת) – WTF ?!
אז בגלל זה אני למשל לא הייתי יכול לעדכן את הראוטר לגרסה חדשה יותר של TP-Link, כי אין להם הורדה של גרסה "ישראלית" המגבילה תדרים (מצטער אבל זה הזוי).

אז התקנתי openwrt, ופתאום נזכרתי לטובה במוקו, אשר דרש ממני קצת האקינג בשביל לגרום לו לעבוד.
מצאתי את עצמי ב7 בערב עד 1 לפנות בוקר מתאים אותו לצרכים שלי.

זה כיף להיכנס למכשיר דרך telnet ולהתחיל להגדיר את הפצת הלינוקס כפי שאתה רוצה. וזה עוד יותר כיף, כשמערכת החבילות זהה למוקו 🙂 .
אחרי שאתה מגדיר סיסמה ל root, ה telnet מתבטל, ואתה חייב לעבוד עם ssh, שגם עברה מספר שיפצורים על ידי.

אני קיבלתי את הראוטר עם חומרה v1.7, שזה השיפצור האחרון של tplink (נכון לכתיבת הפוסט הזה) בנושא החומרה, ונראה שהכל עובד מהקופסא, אחרי שאפשרתי מספר דברים 🙂

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

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

הראוטר של בזק מנתק את ה wifi כל כמה זמן לכמה שניות. כלומר את המכשירים המחוברים אליו.
מדפסת הרשת שלי, משום מה לא עובדת כמו שצריך עם הראוטר הזה, אבל הכי גרוע זה ה TR-069 שיש בראוטר ואני לא יכול לבטל אותו, הוא סוג של back-door  לכל הראוטרים האלו, המאפשרים לבזק לבצע provision מרחוק, אבל מסכנים את הראוטר לחלוטין.

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

אני יכול לבצע אפילו התקנת freeswitch עליו, מגרסת הפיתוח (משום מה), שלא לדבר על אסטריסק, או yate.
התקנה של מרכזיה כדוגמת freeswitch למשל, מאפשרת אם מתבצעת נכון, להעביר את הכוח לסוג של DMZ, שמוגן מתקיפות למינהן, אבל כן מסוגל לבצע שיחות.
אך אין לי כוונה להתקין מרכזיה כלשהי על הראוטר.
אם זה לא מספיק, אני יכול גם להתקין את Kamailio מסדרת שלוש וסדרת ארבע, מה שאומר שאני גם יכול לקבל SIP Proxy שאני יכול לתכנת כפי שאני רוצה, אך גם כאן, זה לא יהיה מה שאעשה.

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

בכל מקרה, אני מאוד נהנה 🙂

מזלגות נעוצים

בתקופה האחרונה, נעשו מספר פעולות fork לפרויקטים מוכרים, בהם node.js ודביאן.
בנוסף, פרויקט docker מקבל מתחרה, לאחר שחברת CoreOS הודיעה כי לא מקובל עליה הכיון של docker.

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

אתחיל בדביאן
יש המון טינה על systemd, ובעקבות כל הנושא, עם כל הזעם, הוחלט ליצור fork בשם devuan, אשר ימשיך לספק יכולות של sysv init במקום systemd ה"נורא".

החשיבה כאילו systemd גוזל משהו, בכך שהוא בא לסדר בלאגן ובעיות שיש במערכת הקיימת כיום, מקבלת תירוצים של "נוצרת תלות במערכת", והתשובה שלי היא: "כי עד עכשיו התלות ב sysv לא היתה קיימת ?"

המאבקים המפגרים האלו, האם להשתמש בsystemd או לא, פוגעים בלינוקס, ולא האם systemd טוב או לא.

node.js
לפני מספר חודשים הבעתי חשש לגבי הפרויקט, והתלות שלו בגוגל. מסתבר שאני לא היחיד שמפחד ממעורבות של חברות בצורה כל כך דרסטית בפרויקט, אז קבוצה של מתכנתים שמפתחים ל node.js בהתנדבות, החליטו לנעוץ מזגל בפרויקט, וליצור את הפרויקט io.js.

הרעיון הוא לא להיות תלוי בהחלטות של חברה מסחרית בפרויקט, ובכך להשאיר אותו פתוח בתפיסה, אם כי זה לא אומר שהתפיסה של המפתחים תהיה מוסכמת על שאר השוק …

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

Rocket
במידה ולא שמעתם על docker, אתם כנראה ישנים איפשהו, או שרחוקים מעולם ה IT. זה השם החם ביותר מאז שסייבר ומחשוב ענן נכנס לעולם, או אולי זה היה 42 ?

docker במקור הוא סוג של container אשר מאפשר לקחת תמונה כלשהי ולהריץ אותה ולבצע דבר מה צורה מבודדת משאר המחשב, אבל תוך שימוש בברזל ולא שימוש בוירטואליזציה.
זה למעשה העולם הבא אחרי הפרה-וירטואליזציה,היות ו containers עד לדוקר היו שייכים לחלק ממערכת ההפעלה עליה הם רצים, אבל דוקר מאפשר להריץ מערכת לגמרי שונה ב container תוך שימוש בברזלים, ולכן ככה אני לפחות רואה אותו.

דוקר התחיל ללכת למחוזות שלא נראים לCoreOS – חברה המתמחה במתן פתרונות של פריסה אוטומטית של שרתים, ואחד הלקוחות הגדולים ביותר המשתמשים בדוקר (כנראה).

החברה של CoreOS, רוצים container ומשהו שזו כל ההתמחות שלו, אבל docker מתחיל להיות stack שלם של דברים, והם ממש לא אוהבים את זה, כי בסופו של דבר,זו סוג של תחרות, לא ?

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

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

systemd

זהירות פוסט ארוך מאוד

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

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

מהפכה נוספת, היא החלפת הגישה של sysv כמעט לגמרי, עם מנהלי init שונים, כאשר זה שלוקח את הכי הרבה אש, וגם בשימוש הרב ביותר הוא systemd. זה השם שלו, כפי שהוא כתוב. והd בסוף מצייג כמובן את המילה daemon, כי הוא יושב ב pid 1, ומנהל את העליה של כל השאר, אחרי שמנהל האתחול (כדוגמת grub) מריץ אותו.

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

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

בניגוד ל init הישן, ולדעתי הלא טוב, systemd מביא איתו גישה חדשה, אך בראש ובראשונה הוא פותר בעיות שפעם לא נחשבו לכאלו, וחלקם גם לא התקיימו, אבל כיום הן כן – תאימות בכתיבת services בראש ובראשונה. להמשיך לקרוא

סידור תיבות דואר

יש לי חבר קיבל פרויקט בעבודה שלו – סידור מחדש של שרתי דואר של לקוחות החברה (חברת ISP), ולמרות שהם כולם בתוצרת maildir, הם מסודרים בצורה לא קבועה, וחלקם נמצאים בספרייה בשם mbox למשל, למרות שהם לא בפורמט הזה.

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

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

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

  • חיפוש תתי ספריות ברקורסיה
  • איטרציה על קבצים
  • ביצוע פילטר על תוכן במערך
  • יצירת ספריות
  • העתקת תוכן של ספריות בצורה רקורסיבית

טיפים על עבודה ב ssh

כאשר פותחים חיבורים של ssh,אנחנו מקבלים משהו שנקרא channels, שהם בעצם הצורה ש ssh מזהה את החיבורים שלנו על אותה "מנהרה" שמוצפנת.
חשוב להדגיש כי חיבור לשרתים שונים, לרוב לא יכללו את אותה המנהרה, אלא רק חיבורים לאותו השרת, אך כל חיבור מכיל channels.
אני נוהג להשתמש בצורה שבה כל חיבור לשרת, משתמש בsocket בודד, וכך עושה את החיבור יעיל אפילו יותר – היות וגם ככה כל חיבור מנוהל על ידי channel.

בשביל להתחיל לעבוד בגישה הזו, של מספר חיבורים בו זמנית על אותו הsocket ניצור תחת ספריית הבית שלנו תת ספרייה (עם נקודה בהתחלה) בשם ssh. .במידה והיא קיימת, זה מצויין.

בתוך הספרייה ניצור קובץ בשם config ונכנס לו את ההגדרה הבאה:

Host *
  ControlPath ~/.ssh/sockets/master-%l-%r@%h:%p
  ControlMaster auto
  GSSAPIAuthentication=no
  ServerAliveInterval 25
  Compression yes
  IdentityFile ~/.ssh/id_rsa

ה"חלק" הזה שיצרנו בעצם יוצר קבוצה של הגדרות עבור 100% מהחיבורים שלנו (אלא אם נדרוס אותן). אנחנו יודעים זאת, בזכות הglob של כוכבית.
אנחנו אומרים לו ליצור קובץ socket על שם החיבור המדויק שלנו, ושopenssl ינהל אותו לבד. מדובר למעשה ב unix socket, וזה מה שמאפשר את השיתוף.
אנחנו אומרים למערכת שלנו כל 25 שניות לשלוח סוג של ping בשביל להשאיר את החיבור פתוח (אחרת יש חיבורים שיסגרו בשרתים שונים אם אין תגובה אחת לזמן מסוים), אנחנו דוחסים את המידע העובר עם החיבור, ובסוף אומרים מה המפתח ברירת המחדל שלנו.

כל האופציות האלו, הן אופציות שניתן להגדיר גם בשורת הפקודה, וגם תחת ssh_config שנמצא ב etc, אך כאן אנחנו עוקפים את ההגדרות של הקובץ האחרון, ובנוסף אין צורך ליצור משהו בשורת הפקודה, ואפילו alias מיותר.
בשורת הפקודה אנחנו מגדירים את רובם עם הדגל של ‎-o, ואז מציינים את ההגדרה שרוצים.

הקובץ של config מאפשר לנו גם לבצע הגדרות מדוייקות לשרתים שונים. למשל: להמשיך לקרוא

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

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

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

הגעתי אל המשרדים של השותף, במטרה ליום שלם של מחקר בנושא. ובאיזשהו שלב, גם הצלחתי לשחזר את הבעיה – ובעיה זו היתה מאוד קשה לשחזר, ולמעשה רק אחרי הצהריים הצלחתי להגיע אליה, למרות שהתחלתי את המחקר ב9 בבוקר.

הפעלתי wireshark, וגיליתי כי three way handshake אינו מתבצע עד הסוף, ולמעשה ה ACK האחרון לא נשלח חזרה על ידי השרת (ה wireshark היה על השרת עצמו).
יש מספר נסיונות שליחה של לחיצת היד, ובסוף יש RST על הבקשה כי לא ניתן היה ליצור קשר, והבקשה התנתקה.

גוגל לא עזר בכלל, כנראה שהבעיה מדוייקת מידי וקשה להסביר אותה במילים, ובסוף נשברתי, ושמתי nginx על אחד השרתים, ושום דבר לא חזר על עצמו, כלומר המערכת עבדה חלק בלי שום בעיות למשך יום וחצי של עבודה עוד.
לפני ה nginx ניסיתי אפילו את שרת הפיתוח של PHP בנושא, וגם אצלו לא היו בעיות שונות, הבעיה היתה רק באפצ'י. אם בהתחלה חשבתי שאולי יש באג בTCP Stack של לינוקס, זה די כיוון אותי לכיוון האפצ'י.

בנתיים דיברתי עם בוריס, והוא הצליח למצוא קישור מעניין שמדבר כי אפצ'י בברירת המחדל מגיע עם דגל של TCP_DEFER_ACCEPT. עד כמה שאני מבין, הדגל הזה אומר לשרת לא לחכות ל three way handshake, אלא במידה ונשלח מידע אחרי החיבור הראשוני, כשעוד אין ACK, אלא רק SYN-ACK, ניתן כבר לקבל את המידע, ולמעשה רק כשהוא יסתיים להישלח, ישלח גם ה ACK.

מסתבר שבאפצ'י 2 הדגל מאופשר בברירת המחדל (בניגוד לnginx ששם צריך להגיד לו את זה במפורש), ולכן צריך לכבות אותו.

בשביל לכבות את הדגל בחיבור, צריך לשים ב httpd.conf הראשי, את הקוד הבא:

 AcceptFilter http none

במידה ויש הגדרה אחרת בנושא, למשל עם data, יש לשכתב אותה לnone.
וזה מכבה למעשה את הדגל של TCP_DEFER_ACCEPT ועכשיו אפצ'י חייב לחכות ללחיצת היד כמו שצריך לפני שיוכל לנתח את מה שנשלח.

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