-->

יום שני, 21 באפריל 2014

לינוקס/אובונטו - התנהלות עם קבצים, ההתחלה...

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

הערה: קצת מוזר לומר שמשהו ב Linux דומה לחלונות. המקור ממנו שתיהן הושפעו הוא כמובן UNIX, כאשר Linux הושפעה מאוד מ UNIX, וחלונות - רק במעט. בגרסאות האחרונות (Windows server 2003 ומעלה) ניתן לראות יותר מנגנונים בחלונות שדומים ל UNIX (ביצוע פעולות עם super user, יציאה מה registry לתיקיות קונפיגורציה, כל ההתפתחות של power shell, ועוד) - אולי בכדי לסגור פערים מול פ'יצרים מוערכים בלינוקס.


פוסט זה הוא חלק מהסדרה: לינוקס / אובונטו




נחזור ל path. בכדי כדי לבדוק את ה path שכרגע מקונפג במערכת נקליד:

echo $PATH | tr ':' '\n'

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

* יש פה גם pipe. אם אתם לא מכירים - קפצו לפוסט הקודם בסדרה או חפשו בגוגל.

הנה תוצאת הפקודה על המחשב שלי:



כמה הסברים על התוצאה - מדוע כך נראה PATH ברירת-המחדל:
  • לינוקס מפרידה בין executables לשימוש כללי (תיקיות bin; קבצים לדוגמה: ls או cat) ו executables המשמשים את מערכת ההפעלה עצמה (תיקיות  sbin; קבצים לדוגמה: reboot, init או mkfs [א]).
  • תיקיות bin/ ו sbin/ (ישירות תחת ה root) - הן עבור executables שצריכים להיות זמינים בשלב מוקדם של ה boot sequence של מערכת ההפעלה, לפני שהתבצע mount לתיקיית ה usr/
  • תיקיית usr/, בניגוד ליוניקס או חלונות, היא איננה תיקיית "user data" אלא "user applications".
  • תיקיות */usr/local/ נועדו לאפליקציות (או סקריפטים) שאנו מוסיפים למערכת. הם לא חלק מהמערכת  ו / או מנוהלים ע"י ה package manager. אפליקציות שמגיעות דרך ה package manager לא יכולות להיות מותקנות בתיקיית ה local.
  • משחקים? על ubuntu server? אולי לשעות המתות של ההתקנות... (התיקיות עצמן ריקות).


נחזור לפקודה עצמה:

echo - אנחנו מכירים (אמורים להכיר מפוסט קודם). שלא כמו בחלונות, יש להקפיד על upper-case ב PATH (או כל משתנה אחר).

tr (קיצור של transliterate, אפשר לזכור את זה כקיצור של translate) הוא בעצם סוג של כלי search-replace. אנו מחליפים את ":" (ה separator בין paths במשתנה PATH) לשורה חדשה. מתכנתים אמורים להרגיש נוח עם n\.

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

echo $PATH | tr ':' '\n' | tr 'a-z' 'A-Z'

תחליף גם אותיות לטיניות ל upper case.


אם אנו באים מרקע של חלונות, אולי כדאי להציג את ה PATH בצורה יותר מוכרת, ב "Windows format"?     ;-)

echo $PATH | tr ':' '\n' | tr 'a-z' 'A-Z' | tr '/' '\\' | sed -e 's/^/C:/'

הנה התוצאה:


לא להיבהל אם הפקודה עמוסה בסימנים. חתכו בראש את ה pipes ועברו שלב-שלב: אלו שלבים פשוטים.
את ההתחלה אתם כבר מכירים. עבור התו \ היינו זקוקים ל escaping (\\). את ההוספה של :C בתחילת כל שורה לא יכולתי לעשות בעזרת tr: מכיוון ש tr מחליפה כל סימן בסימן אחר (או כלום) - אך היא לא יכולה לטפל במחרוזות ארוכות יותר ":C". הקלידו man tr בשורת הפקודה כדי ללמוד על כמה אופציות נוספות שיש לה (בעיקר זיהוי סימנים טוב יותר או העלמה יעילה של תוים - החלפה בכלום).
כש tr הפשוטה לא מספיקה - עוברים ל sed (קיצור של stream editor).

sed היא פקודה רבת-עוצמה המאפשרת חופש פעולה רב מאוד. במקרה הזה השתמשתי בה בכדי לבצע החלפת טקסט דומה ל tr. הפרמטר e- אומר שאני רוצה לעבוד עם sed script (מה שבמרכאות) והפתיחה באות s היא פקודה ב sed script בפורמט "/s/regex/replacement". כלומר: ה regex הוא ^ (תחילת שורה) וההחלפה היא המחרוזת ":C". / הם רק separators בין הפרמטרים.

צחקנו קצת - יופי.



הוספה ל path
נניח ואנו רואים את ה path ולא מרוצים ממנו. אנו רוצים להוסיף לו את התיקיה: usr/local/games/2048/ כדי שהמשחק (בגרסה ה shell-ית שלו) יהיה זמין לנו להפעלה מכל מקום ובכל רגע.

2048. גם אנשי bash - מתמכרים. מקור: לינמגזין - מגזין טכנולוגיה וקוד פתוח.


כדי להוסיף למשתנה path יש לכתוב:

PATH=$PATH:/usr/local/games/2048

תחביר דומה ל x = x + n. שימו לב שאנו זקוקים prefix של $ בכדי לקרוא את הפרמטר PATH - אך לא כדי לכתוב לתוכו.


יש לנו בעיה: לאחר login מחדש עם ה shell - ה PATH יחזור למצבו הקודם.
הסיבה: בכל התחברות מחדש עם SSH - רץ סקריפט שדורס את משתנה ה PATH.

מה נעשה? נדרוס אותו עוד פעם בעצמנו.



אתנחתא קלה

שניה! בחלונות אני מגדיר משתני סביבה - והם קבועים.
מה זה ה hack הזה בלינוקס שכותבים סקריפט שבכל התחברות ידרוס משהו קבוע? מה לא בסדר בלינוקס?!

ובכן, הכל בסדר בלינוקס. לינוקס פשוט - גלויה יותר.
גם בחלונות רצים scripts להגדרת הסביבה בכל פתיחה שלה (יהיה זה PowerShell, cmd, או Connect-WSMan) - פשוט מערכת ההפעלה מחביאה פרט זה מהמשתמש. כל script כזה הולך למקום בו שמורים ה environment variables ויוצר אותם בסביבה. אפשר בקלות רבה לממש לוגיקה דומה בלינוקס: קובץ משתנים וסקריפט שנטען לכל משתמש ויוצר את המשתנים הללו בסביבה.

הדרך המקובלת בלינוקס היא פשוט להוסיף עוד שורה ל script האתחול.
בהפעלה של ssh - רצים כמה סקריפטים:
  1. etc/profile/ - סקריפט אתחול לכלל המשתמשים
  2. profile./~ - סקריפט אתחול למשתמש, שבעקרון קיים בשביל תאימות-לאחור (אך בהחלט אפשר להשתמש בו)
  3. bash_profile./~ סקריפט שרץ בזמן login של המשתמש
  4. etc/bash.bashrc/ סקירפט אתחול לכלל המשתמשים בעת הפעלה של bash ב interactive mode (קרי טרמינל או SSH).
  5. bashrc./~ סקריפט אתחול למשתמש בעת הפעלה של bash ב interactive mode.
רשימת הסקריפטים שנטענים תהיה שונה אם עובדים עם shell אחר, למשל ksh (קיצור של kornShell).
בד"כ עורכים את bashrc/~ (כלומר: בתיקיית הבית של המשתמש), אם רוצים להשפיע על המשתמש הבודד ב bash.
אם מדובר על משתני סביבה שיהיו בשימוש עבור איזה תהליך שרץ עבור המשתמש, בלי שהוא מחובר אינטרקטיבית - יש לערוך את profile./~ בכדי לקבל את התוצאה הרצויה.

איך עושים זאת בצורה פשוטה מקוצרת [ב]?

echo 'PATH=$PATH:/usr/local/games/2048' >> ~/.bashrc


"<<" עובד בדיוק כמו שעובד בחלונות (הוספה לסוף קובץ),  כך שלא משנה מה יש בקובץ - הוספה לסופו היא בטוחה למדי (כלומר: יחסית. כל מה שיכול להשתבש - אכן ישתבש).


"Unix is user-friendly. It just isn't promiscuous about which users it's friendly with." – "Steven King, Software Archaeologist"


עוד טיפ קטן: לפעמים אתם רוצים לדעת איפה executable יושב: אולי חסרות לו הרשאות, ואולי לכם הוא זמין ב PATH ולחברכם לא - אבל אתם לא רוצים לזרוק עליו עשרה paths שאתם משתמשים בהם. פקודת which מחפשת ב PATH (ללא כניסה ל symbolic links) אחר executables ומדווחת על מיקומם:




סיכום

בחיי שרציתי לדבר על ניהול קבצים! ניהול הרשאות עם chmod, חיפוש עם find, אולי symbolic links, אולי משהו נוסף.
אבל - קצת נגררתי. אני רוצה לכסות את הנושאים בהם אני נוגע בצורה מעמיקה, כך שמי שקורא יבין ולא רק "ידע" - אבל בלינוקס זה אומר כנראה שיש הרבה מאוד מה ללמוד.

נראה לי שמשיך עוד קצת, עד שימאס לי או שאראה (ע"פ השימוש) - שלכם הקוראים זה נמאס.

שיהיה בהצלחה!



---

[א]  קיצור של make file system

[ב] הדרך הפשוטה להוסיף שורה בסוף הקובץ הוא לפתוח אותו ב editor כלשהו ולראות בעיניים מה עושים (אלא אם עושים זאת בסקריפט).

ה UNIX WAY אומרת: Clarity is better than cleverness. בטוח שהרבה כותבי סקריפטים בלינוקס לא הולכים לפי כלל זה. הנה דוגמה לסקריפט למעלה כשהוא "מתוחכם", אך לא קריא (לטעמי):

echo $PATH | tr ':/a-z' '\n\\A-Z' | sed -e 's/^/C:/'




3 תגובות:

  1. תמשיך תמשיך... :-)

    השבמחק
  2. תודה רבה!
    למדתי המון מהפוסטים האחרונים.

    השבמחק
  3. תודה רבה!
    הכתיבה שלך קולחת וההסברים מצוינים!

    השבמחק