לכתוב תנאים
רמת קושי: #beginners
כתיבה של תנאי בבאש יכולה להתבצע במספר דרכים, התנאי הפשוט נראה בצורה הבאה בה הביטוי ממוקם בין סוגריים
התנאי בודק את הביטוי ואם הוא true מה שבתוך התנאי יתממש.
חשוב לציין, תנאי בבאש לא מחזיר true או false אלא 0 ששוה בעצם לtrue ו 1 ששוה ערך ל false. התנהגות זו שונה מרוב שפות התכנות והסיבה לכך היא שרוב העבודה בבאש היא שימוש בהרבה תוכניות קטנות לבצע מטלה גדולה יותר כך שהתנאי בעצם בודק את הסטטוס קוד שהתוכנית מחזירה, סטטוס קוד 0 שווה לתוכנית שהסתיימה בהצלחה.
(למען הנוחות מכאן והלאה אתייחס ל 0 כ true ו 1 כ false)
קיצורים רבותיי
ישנה דרך מקוצרת לכתוב תנאי
מה שקורה פה הוא שאנו מריצים ביטוי שיחזיר לנו true או false, במידה והוא יחזיר true אז הוא ימשיך לקוד הבא, במידה וביטוי שלנו החזיר false מה שנמצא לאחר ה
הטריק הזה כמובן יעבוד גם בצורה ההפוכה על ידי שימוש ב
מה לא לעשות?
הדרך הקצרה לפעמים היא הדרך הכואבת וזה נכון גם במקרה הזה, בעוד ששימוש בתנאי רגיל יחזיר תמיד סטטוס קוד 0 וזה לא משנה אם הביטוי החזיר true או false
$
$
שימוש בתנאי מקוצר מחזיר סטטוס קוד 1 במידה והביטוי החזיר false
$
$
$
1
זה כבר הופך להיות בעיה של ממש, במיוחד אם הסקריפט משולב כחלק מה pipeline.
#if
#exit_code
#conditions
@bash_tips
רמת קושי: #beginners
כתיבה של תנאי בבאש יכולה להתבצע במספר דרכים, התנאי הפשוט נראה בצורה הבאה בה הביטוי ממוקם בין סוגריים
if [[ 1 -eq 1 ]]
then
echo "I'm in"
fi
התנאי בודק את הביטוי ואם הוא true מה שבתוך התנאי יתממש.
חשוב לציין, תנאי בבאש לא מחזיר true או false אלא 0 ששוה בעצם לtrue ו 1 ששוה ערך ל false. התנהגות זו שונה מרוב שפות התכנות והסיבה לכך היא שרוב העבודה בבאש היא שימוש בהרבה תוכניות קטנות לבצע מטלה גדולה יותר כך שהתנאי בעצם בודק את הסטטוס קוד שהתוכנית מחזירה, סטטוס קוד 0 שווה לתוכנית שהסתיימה בהצלחה.
(למען הנוחות מכאן והלאה אתייחס ל 0 כ true ו 1 כ false)
קיצורים רבותיי
ישנה דרך מקוצרת לכתוב תנאי
[[ 1 -eq 1 ]] && echo "do it"
מה שקורה פה הוא שאנו מריצים ביטוי שיחזיר לנו true או false, במידה והוא יחזיר true אז הוא ימשיך לקוד הבא, במידה וביטוי שלנו החזיר false מה שנמצא לאחר ה
&&
לא יבוצע.הטריק הזה כמובן יעבוד גם בצורה ההפוכה על ידי שימוש ב
||
כך שהמשך הקוד יתבצע רק עם הביטוי יכשל.מה לא לעשות?
הדרך הקצרה לפעמים היא הדרך הכואבת וזה נכון גם במקרה הזה, בעוד ששימוש בתנאי רגיל יחזיר תמיד סטטוס קוד 0 וזה לא משנה אם הביטוי החזיר true או false
$
cat /tmp/test.sh
#!/bin/bash
if [[ 1 -eq 0 ]]
then
echo "I'm in"
fi
echo $?
$
bash /tmp/test.sh
$ echo $?
0שימוש בתנאי מקוצר מחזיר סטטוס קוד 1 במידה והביטוי החזיר false
$
cat /tmp/test.sh
#!/bin/bash
[[ 1 -eq 0 ]] && echo "Do it"
$
bash /tmp/test.sh
$
echo $?
1
זה כבר הופך להיות בעיה של ממש, במיוחד אם הסקריפט משולב כחלק מה pipeline.
#if
#exit_code
#conditions
@bash_tips
לכתוב תנאים - הרחבה
רמת קושי: #beginners
מספר דרכים לכתוב תנאי בבאש, להלן קצת סדר
סוגריים עגולים כפולים (( ))
סוג תנאי שעובד רק על מספרים ומתאים לבדיקת פעולות חשבוניות.
פקודה הבודקת ביטויי השוואה ממש כמו if, מחזירה true ל0 וfalse לכל מה שאינו 0
פקודה המבצעת בדיוק את את אותן פעולת שמבצעת פקודת test, ההבדל היחידי בין השניים הוא שפקודת test תגיב לדגלי
חשוב לשים לב שמשתמשים ותיקים עלולים לתהות מה ההבדל בין
ובכן, בעוד הראשון הוא לעתים פקודה בפני עצמה (מקבילה ל־
$
למשל, במקום
אופרטור =~ מה חשוב לדעת?
חשוב רק לציין שבמידה ומשתמשים באופרטור ההשוואה
$
קרדיט: תודה רבה לתומר @tomer מקבוצת @linux_il על הפוסט! (אז מה אם הוא השתנה מעט)
למי שלא מכיר קבוצת לינוקס ישראל היא אחת הקבוצות היותר טובות והיותר פעילות בטלגרם (כל עוד לא מדברים על קאלי).
#[
#if
#test
#regex
#conditions
@bash_tips
רמת קושי: #beginners
מספר דרכים לכתוב תנאי בבאש, להלן קצת סדר
סוגריים עגולים כפולים (( ))
סוג תנאי שעובד רק על מספרים ומתאים לבדיקת פעולות חשבוניות.
if (( 1 == 1 )); thenפקודת test
...
פקודה הבודקת ביטויי השוואה ממש כמו if, מחזירה true ל0 וfalse לכל מה שאינו 0
test 1 -ne 0סוגרים מרובעים בודדים [ ]
test string1 = string2
test -n string
...
פקודה המבצעת בדיוק את את אותן פעולת שמבצעת פקודת test, ההבדל היחידי בין השניים הוא שפקודת test תגיב לדגלי
--help, ו --version
if [ 1 -ne 0 ]סוגריים מרובעים כפולים [[ ]]
if [ string1 = string2 ]
if [ -n string ]
חשוב לשים לב שמשתמשים ותיקים עלולים לתהות מה ההבדל בין
[
ל [[
. ובכן, בעוד הראשון הוא לעתים פקודה בפני עצמה (מקבילה ל־
test
) $
whereis [
[: /usr/bin/[ /usr/share/man/man1/[.1.gzהשנייה היא רק פקודה מובנית ב־shell ונותנת לנו יכולות מתקדמות יותר.
למשל, במקום
-eq
כדי לבחון שיוויון, אפשר להשתמש בסימן שיוויון נורמלי. if [[ 1 -eq 1 ]]
לעומתif [[ 1 = 1 ]]
וברמת העיקרון אפשר גם לוותר על תחימה במרכאות של מחרוזות שכוללות תו רווח כי ה־shell יצליח להבין איך להתמודד עם זה.if [ -f "$filename" ]
לעומתif [[ -f $filename ]]
כבונוס, ישנו את האופרטור החשוב =~ המאפשר להשתמש בביטויים רגולריים ישירות מתנאי ההשוואה, וכך לחסוך ביטויים לוגיים מורכבים.אופרטור =~ מה חשוב לדעת?
חשוב רק לציין שבמידה ומשתמשים באופרטור ההשוואה
=~
יש הבדל בין משתנה העטוף בגרשיים (להלן מגורגש) לכזה שאינו, ברגע שמעבירים לתנאי משתנה מגורגש הביטוי מחפש את כל מחרוזת הטקסט שבמשתנה בצורה גולמית ולא מנסה להשוות את המשתנה כביטוי regex$
cat file.txt
111+.*pdf{}[]$$
[[ $(cat file.txt) =~ "pdf{}" ]] && echo match
match$
[[ $(cat file.txt) =~ pdf{} ]] && echo match
$ echo $?
1מצד אחד זה מאפשר לנו לבדוק התאמה של תת מחרוזות שמכילות תווים מיוחדים בצורה גולמית, מצד שני מי שלא מכיר את צורת התנהגות זו עשוי לבזבז זמן ולתהות מדוע דברים אינם מתנהגים כמצופה.
קרדיט: תודה רבה לתומר @tomer מקבוצת @linux_il על הפוסט! (אז מה אם הוא השתנה מעט)
למי שלא מכיר קבוצת לינוקס ישראל היא אחת הקבוצות היותר טובות והיותר פעילות בטלגרם (כל עוד לא מדברים על קאלי).
#[
#if
#test
#regex
#conditions
@bash_tips
שימוש בsed עם extended regex
רמת קושי: #beginners
טיפ חביב וקצרצר בקשר ל sed, המבנה הבסיסי של הפקודה מתבסס על ביטוי regex ואז הוראה מה נרצה לבצע לכל דבר שתואם לביטוי, העניין הוא שsed ברירת מחדל אינו משתמש בתצורה המורחבת של regex.
בכדי לאפשר extended regex לsed ניתן להשתמש בדגל
#regex
#extended_regex
@bash_tips
רמת קושי: #beginners
טיפ חביב וקצרצר בקשר ל sed, המבנה הבסיסי של הפקודה מתבסס על ביטוי regex ואז הוראה מה נרצה לבצע לכל דבר שתואם לביטוי, העניין הוא שsed ברירת מחדל אינו משתמש בתצורה המורחבת של regex.
בכדי לאפשר extended regex לsed ניתן להשתמש בדגל
-E
או -r
$ sed -E 's/something_(aaa|bbb|ccc)//g#sed
#regex
#extended_regex
@bash_tips
עושים שיפט
רמת קושי: #advanced
אנו מכירים את צורת העברת פרמטרים לסקריפט באש, כל פרמטר מקבל מספר וניתן לגשת לפרמטרים לפי האינדקס שלהם על ידי $
לדוגמה אנו רוצים לבנות סקריפט שמדפיס את כל הפרמטרים שהוא מקבל, לשם כך נשתמש ב $*
פקודת shift היא כלי שמגיע כחלק מ bash builtin ומה שהיא נותנת זה "להזיז" את הפרמטרים מספר צעדים קדימה כך שהפרמטר הראשון יוסר מהרשימה ומה שהיה לפני כן במשתנה $2 יהפוך להיות $1
הטריק כמובן יעבוד גם על פונקציות
#shift
#scripting
#function
#parameters
@bash_tips
רמת קושי: #advanced
אנו מכירים את צורת העברת פרמטרים לסקריפט באש, כל פרמטר מקבל מספר וניתן לגשת לפרמטרים לפי האינדקס שלהם על ידי $
$ cat test.shלעיתים צורת העברה של פרמטרים לפי אינדקס יוצרת לנו בעיה, כי לא תמיד נרצה להעביר את כל הפרמטרים
echo $1
echo $2
echo $3
$ bash test.sh one two three
one
two
three
לדוגמה אנו רוצים לבנות סקריפט שמדפיס את כל הפרמטרים שהוא מקבל, לשם כך נשתמש ב $*
$ cat test.shמה קורה אם אנו רוצים שהפרמטר הראשון יהיה הוראה להדפיס את התוכן כ base64 וששאר הפרמטרים יודפסו כרגיל? אם ננסה את הפתרון ממקודם פשוט נדפיס גם את ההוראה בעצמה כחלק מהטקסט
echo "$*"
$ bash test.sh one two three
one two three
$ bash test.sh base64 one two threeפתרון אפשרי הוא לקחת את המערך של הפרמטרים ולהעביר את כל הפרמטרים חוץ מהפרמטר הראשון, ואת הפרמטר הראשון לשמור במשתנה נפרד
base64 one two three
action=$1דרך נקייה יותר לעשות את אותו הדבר היא להשתמש בפקודת shift
echo "${*:2}"
פקודת shift היא כלי שמגיע כחלק מ bash builtin ומה שהיא נותנת זה "להזיז" את הפרמטרים מספר צעדים קדימה כך שהפרמטר הראשון יוסר מהרשימה ומה שהיה לפני כן במשתנה $2 יהפוך להיות $1
$ cat test.shאם ניקח את הפתרון הזה לבעיה שהצגנו מקודם אפשרי יהיה לפתור את בעיית הפרמטרים בצורה הבאה
shift 1
echo $1
echo $2
echo $3
$ bash test.sh one two three
two
three
action=$1משתנה action מקבל את ההוראה אותה אנו רוצים להעביר לסקריפט, ואז אנו "מוחקים" אותו מרשימת הפרמטרים ומעבירים את שאר הפרמטרים הלאה.
shift 1
echo "${*}"
הטריק כמובן יעבוד גם על פונקציות
#shift
#scripting
#function
#parameters
@bash_tips
מפות ומערכים
רמת קושי: #beginners
בעבר דיברנו על מערכים וההפתעות שאנו עשויים להיתקל בהן, ישנם מספר דרכים ליצור מערכים בצורה בטוחה, זוהי הדרך ליצור מערך של שורות מקובץ .
פקודת
כברירת מחדל הפקודה טוענת את התוכן שלה למשתנה סביבה בשם
במידה ונעביר שם של משתנה התוכן יכניס למשתנה אותו העברנו
כפי שניתן להעביר קובץ, ניתן גם להעביר תוכן של משתנה למערך על ידי שימוש ב here-string
#array
#mapfile
#readarray
@bash_tips
רמת קושי: #beginners
בעבר דיברנו על מערכים וההפתעות שאנו עשויים להיתקל בהן, ישנם מספר דרכים ליצור מערכים בצורה בטוחה, זוהי הדרך ליצור מערך של שורות מקובץ .
פקודת
mapfile
והמקבילה שלה בבאש readarray
, הן בעצם אותו כלי שכל תפקידו זה לקבל תוכן מה stdin וליצור מערך לפי מספר השורות שיש בתוכן.כברירת מחדל הפקודה טוענת את התוכן שלה למשתנה סביבה בשם
MAPFILE
וצורת הפעולה שלה נראית כך.
$ mapfile < myfile
$ echo ${MAPFILE[@]}
one
two
three
במידה ונעביר שם של משתנה התוכן יכניס למשתנה אותו העברנו
$ mapfile mylist < myfile
$ echo ${mylist[@]}
one
two
three
כפי שניתן להעביר קובץ, ניתן גם להעביר תוכן של משתנה למערך על ידי שימוש ב here-string
$ mapfile mylist <<< "$myvar"
$ echo ${mylist[@]}
one
two
three
#array
#mapfile
#readarray
@bash_tips
מערכים ומפות read
רמת קושי: #beginners
בפוסט הקודם דיברנו על פקודת mapfile / readarray ואיך יהיה נכון יותר ליצור מערך של שורות מקובץ מבלי לבצע פעולות שלא אליהן התכוונו, מה אם מה שאנו צריכים זה ליצור מערך של מילים משורה בודדת?
את פקודת read ראינו בפוסטים קודמים, הפקודה מאפשרת לקבל ערכים מה stdin למשתנה, בצורתה הפשוטה הפקודה מעבירה את הקלט כמחרוזת, עם זאת ניתן לקבל את הקלט כמערך על ידי שימוש בפרמטר -a
חשוב לשים לב, הפקודה תיקח רק את השורה הראשונה שהועברה אליה ותפצל אותה למערך, ולכן במידה ומעבירים מחרוזת של מספר שורות כדאי להתשמש ב read while כפי שראינו בעבר, ולפצל את השורה כפי שראינו זה עתה.
#read
#array
@bash_tips
רמת קושי: #beginners
בפוסט הקודם דיברנו על פקודת mapfile / readarray ואיך יהיה נכון יותר ליצור מערך של שורות מקובץ מבלי לבצע פעולות שלא אליהן התכוונו, מה אם מה שאנו צריכים זה ליצור מערך של מילים משורה בודדת?
את פקודת read ראינו בפוסטים קודמים, הפקודה מאפשרת לקבל ערכים מה stdin למשתנה, בצורתה הפשוטה הפקודה מעבירה את הקלט כמחרוזת, עם זאת ניתן לקבל את הקלט כמערך על ידי שימוש בפרמטר -a
$ myline="one two three"
$ read -a mylist <<< "${myline}"
$ declare -p mylist
declare -a mylist='([0]="one" [1]="two" [2]="three")'
חשוב לשים לב, הפקודה תיקח רק את השורה הראשונה שהועברה אליה ותפצל אותה למערך, ולכן במידה ומעבירים מחרוזת של מספר שורות כדאי להתשמש ב read while כפי שראינו בעבר, ולפצל את השורה כפי שראינו זה עתה.
#read
#array
@bash_tips
לקבל ערך
רמת קושי: #advanced
פונקציונליות נחמדה שקיימת בבאש מאפשרת להעביר ערך של משתנה על ידי השם של המשתנה עצמו, ולפני שמכבסת המילים הזאת עושה לנו כאב ראש בא נראה קצת קוד
זהו הקוד שלנו יש לנו 2 משתנים, האחד מכיל ערך והשני מכיל את השם של המשתנה הראשון, באש מאפשרת לנו לקבל את לקבל את הערך של המשתנה הראשון על ידי קריאה של המשתנה השני, כל זאת על ידי שימוש ב
מה היה לנו כאן?
שני השורות הראשונות דיי ברורות לנו, אנו קוראים למשתנה שמכיל מחרוזת והמחרוזת מודפסת, בשורה האחרונה לעומת זאת מתרחש החלק המעניין, אנו מדפיסים את השם של המשתנה (
להלן דוגמה פשוטה שממחישה איזו בעיה תכונה הזו יכולה לפתור
#indirect_references
#indirect_expansion
@bash_tips
indirect references
רמת קושי: #advanced
פונקציונליות נחמדה שקיימת בבאש מאפשרת להעביר ערך של משתנה על ידי השם של המשתנה עצמו, ולפני שמכבסת המילים הזאת עושה לנו כאב ראש בא נראה קצת קוד
$ cat test.sh
key="value"
myvar="key"
echo "\${key} = ${key}"
echo "\${myvar} = ${myvar}"
echo "\${!myvar} = ${!myvar}"
זהו הקוד שלנו יש לנו 2 משתנים, האחד מכיל ערך והשני מכיל את השם של המשתנה הראשון, באש מאפשרת לנו לקבל את לקבל את הערך של המשתנה הראשון על ידי קריאה של המשתנה השני, כל זאת על ידי שימוש ב
indirect expansion
, זה נראה כך$ bash test.sh
${key} = value
${myvar} = key
${!myvar} = value
מה היה לנו כאן?
שני השורות הראשונות דיי ברורות לנו, אנו קוראים למשתנה שמכיל מחרוזת והמחרוזת מודפסת, בשורה האחרונה לעומת זאת מתרחש החלק המעניין, אנו מדפיסים את השם של המשתנה (
myvar
) עם !, וזה בעצם שולח את באש לחפש אם קיים לה בזיכרון שם של משתנה בשם של המחרוזת (key
), במידה והתשובה היא כן אנו נקבל את הערך של אותו משתנה (value
) כאילו קראנו למשתנה עצמו.להלן דוגמה פשוטה שממחישה איזו בעיה תכונה הזו יכולה לפתור
$ cat test.sh
read -p "please enter exist ENV vartiable name: " var
echo "variable name ${var}: ${!var}"
$ bash test.sh
please enter exist ENV vartiable name: SHELL
variable name SHELL: /bin/bash
#indirect_references
#indirect_expansion
@bash_tips
👍1
להעביר מערכים לפונקציה
רמת קושי: #advanced
המכניקה של באש בהעברת ערכים היא שכל ערך שמגיע לאחר שם הפונקציה מאוחסן במשתנה, כשרווח הוא זה שמפצל בין הארגומנטים.
מעבר לאפשרות של משתנים גלובלים להלן 2 דרכים שונות להתמודד עם הבעיה
פתרון 1: העברת מחרוזות
הפתרון הראשון הוא פשוט להעביר את המערך כמחרוזת ואז בפונקציה עצמה ליצור מערך חדש על ידי העברה של המחרוזת ל read כפי שראינו בעבר.
בגלל שread מפצל את המחרוזת לפי רווחים, מה יקרה אם אחד האיברים יכיל רווח?
מה שיקרה הוא שאותו איבר יהפוך לשני איברים שונים, לא הדבר שהיינו רוצים שיקרה.
פתרון 2: indirect references
את
יש לנו 2 מערכים, לפונקציה אנו מעבירים את השמות של המערכים מבלי לקרוא להם, בפונקציה עצמה אנו "מחוללים" את שמות המערכים כדי לקבל את הערך שלהם, את כל זה אנו עושים בתוך סוגריים כדי ליצור מהערך שאנו מקבלים מערך.
#array
#function
#arguments
#indirect_references
@bash_tips
רמת קושי: #advanced
המכניקה של באש בהעברת ערכים היא שכל ערך שמגיע לאחר שם הפונקציה מאוחסן במשתנה, כשרווח הוא זה שמפצל בין הארגומנטים.
$ cat test.sh
myFunc(){
echo $1
echo $2
}
myFunc one two
$ bash test.sh
one
two
מה יקרה אם נרצה להעביר מערך לפונקציה? אם ננסה להריץ את הקוד הבא נגלה שבעצם האיבר הראשון הולך למשתנה הראשון בפונקציה והאיבר השני הולך למשתנה השני וכן הלאה myFunc(){
echo $1
echo $2
}
myList=(one two)
myFunc ${myList[@]}
$ bash test.sh
one
two
נוכל לנסות לאסוף את כל הערכים שמגיעים לפונקציה ולהגדיר אותם כמערך על ידי שימוש ב ${@}
בפונקציה, אבל זה יכול לעבוד רק בתנאי שאין לנו עוד ערכים אחרים להעביר לפונקציהmyFunc(){
echo ${@}
echo $2
}
myList=(one two)
myFunc ${myList[@]} new_parameter
$ bash test.sh
one two new_parameter
two
בעיה, איך בעצם כן אפשר להעביר מערכים לפונקציות בבאש?מעבר לאפשרות של משתנים גלובלים להלן 2 דרכים שונות להתמודד עם הבעיה
פתרון 1: העברת מחרוזות
הפתרון הראשון הוא פשוט להעביר את המערך כמחרוזת ואז בפונקציה עצמה ליצור מערך חדש על ידי העברה של המחרוזת ל read כפי שראינו בעבר.
myFunc(){
read -r -a arr1 <<< ${1}
read -r -a arr2 <<< ${2}
declare -p arr1 arr2
}
arr1=(aaa bbb ccc)
arr2=(ddd eee fff)
myFunc "${arr1[*]}" "${arr2[*]}"
$ bash test.sh
declare -a arr1=([0]="aaa" [1]="bbb" [2]="ccc")
declare -a arr2=([0]="ddd" [1]="eee" [2]="fff")
אחלה נראה שעובד נהדר, היכן הבעיה?בגלל שread מפצל את המחרוזת לפי רווחים, מה יקרה אם אחד האיברים יכיל רווח?
מה שיקרה הוא שאותו איבר יהפוך לשני איברים שונים, לא הדבר שהיינו רוצים שיקרה.
פתרון 2: indirect references
את
indirect references
הכרנו בפוסט הקודם, בגדול מה שזה אומר הוא שניתן לקבל איזה ערך של משתנה שנרצה מאיזה חלק בתוכנית על ידי חיפוש שם המשתנה בזיכרון התוכנית$ cat test.sh
myFunc(){
func_arr1=( "${!1}" )
func_arr2=( "${!2}" )
declare -p func_arr1 func_arr2
}
arr1=("aaa" "bbb space" "ccc")
arr2=("ddd" "eee" "fff")
myFunc arr1[@] arr2[@]
אז מה היה לנו פה?יש לנו 2 מערכים, לפונקציה אנו מעבירים את השמות של המערכים מבלי לקרוא להם, בפונקציה עצמה אנו "מחוללים" את שמות המערכים כדי לקבל את הערך שלהם, את כל זה אנו עושים בתוך סוגריים כדי ליצור מהערך שאנו מקבלים מערך.
$ bash test.sh
declare -a func_arr1=([0]="aaa" [1]="bbb space" [2]="ccc")
declare -a func_arr2=([0]="ddd" [1]="eee" [2]="fff")
#read#array
#function
#arguments
#indirect_references
@bash_tips
Forwarded from ToCode
# טיפ באש: השתמשו ב null glob כשצריך
את הלולאה הקצרה הזאת כתבתי בסקריפט בלי לחשוב יותר מדי:
ולמה בלי לחשוב? כי אם הסקריפט
הסיבה לשגיאה המוזרה היא ש bash מפענח את הביטוי
הפקודה הראשונה באמת תדפיס את כל הקבצים והתיקיות מתוך
הדרך הכי קלה לצאת מזה היא להשתמש ב
והפעם לא מקבלים שום פלט. בתוך הלולאה אני מקבל בדיוק את ההתנהגות הרצויה:
הפעם הסקריפט לא ינסה לפתוח קובץ עם השם המוזר
את הלולאה הקצרה הזאת כתבתי בסקריפט בלי לחשוב יותר מדי:
#!/bin/bash -e
for json_file in /data/*
do
echo "Importing JSON file $json_file"
python import_json.py "$json_file"
echo "-- Done"
done
ולמה בלי לחשוב? כי אם הסקריפט
import_json.py
ינסה לפתוח את הקובץ שהוא מקבל לקריאה, והתיקיה ריקה, אנחנו נקבל את השגיאה:FileNotFoundError: [Errno 2] No such file or directory: '/data/*'
הסיבה לשגיאה המוזרה היא ש bash מפענח את הביטוי
/data/*
להיות הטקסט הפשוט /data/*
ולא רשימת שמות הקבצים בתיקיה שם - בגלל שאין קבצים באותה תיקיה. אפשר לראות את זה בדוגמה פשוטה יותר בלי לולאה או פייתון אם פשוט נכתוב את שתי הפקודות:# this will print all the files in /etc
$ echo /etc/*
# but this will just print "/data/*"
$ echo /data/*
הפקודה הראשונה באמת תדפיס את כל הקבצים והתיקיות מתוך
/etc
, והשניה תדפיס פשוט /data/*
. כמובן שהמחרוזת שהודפסה מהפקודה השניה אינה באמת שם קובץ ולכן אי אפשר לפתוח אותה.הדרך הכי קלה לצאת מזה היא להשתמש ב
nullglob
, שזה אומר שאם הביטוי לא מתאים לכלום אז באש יחזיר מחרוזת ריקה. נסו את זה:$ shopt -s nullglob
$ echo /data/*
והפעם לא מקבלים שום פלט. בתוך הלולאה אני מקבל בדיוק את ההתנהגות הרצויה:
#!/bin/bash -e
shopt -s nullglob
for json_file in /data/*
do
echo "Importing JSON file $json_file"
python import_json.py "$json_file"
echo "-- Done"
done
הפעם הסקריפט לא ינסה לפתוח קובץ עם השם המוזר
/data*
ופשוט לא יבצע אף פעם את גוף הלולאה כי באמת אין קבצים שמתאימים לביטוי.פוסט יפה ומפורט מאוד של טל בן שושן על באש
רמת קושי: #beginners
מוזמנים להמליץ על עוד תוכן וקבוצות ישראליות איכותיות
@bash_tips
רמת קושי: #beginners
מוזמנים להמליץ על עוד תוכן וקבוצות ישראליות איכותיות
@bash_tips
לחפש כשמכווץ
לא פעם אנו צריכים לחפש טקסט בערימה של קבצי זיפ, במקום לפתוח קובץ קובץ ולחפש בתוכן, ניתן להשתמש בפקודת
#zgrep
#grep
#zip
@bash_tips
zgrep
רמת קושי: #beginners לא פעם אנו צריכים לחפש טקסט בערימה של קבצי זיפ, במקום לפתוח קובץ קובץ ולחפש בתוכן, ניתן להשתמש בפקודת
zgrep
שעובדת אותו הדבר כמו grep רק בלי הצורך לחלץ את הקבצים לפני כן $ zgrep crash /var/log/syslog*#archives
/var/log/syslog.4.gz ...
/var/log/syslog.5.gz ...
/var/log/syslog.9.gz ...
...
#zgrep
#grep
#zip
@bash_tips
סומסום היפתח
רמת קושי: #beginners
טוב הטריק הבא הוא פחות באש ויותר vscode אבל עדין מועיל מאוד
למי שלא מכיר vscode מגיע עם האופציה לפתוח קבצים מהטרמיל
לא פעם אנו מריצים פקודה כלשהי ואת הפלט אנו רוצים לפתוח ישירות ב vscode, אז כדי לחסוך את העתבק אפשר פשוט לשרשר את המידע לvscode בצורה הבאה
(לא לשכוח Ctrl+C כשרוצים לסגור את החיבור)
#vscode
#code
#stdin
@bash_tips
רמת קושי: #beginners
טוב הטריק הבא הוא פחות באש ויותר vscode אבל עדין מועיל מאוד
למי שלא מכיר vscode מגיע עם האופציה לפתוח קבצים מהטרמיל
$ code myfile.log
מדהים נכון? רגע זה לא הטיפ לא פעם אנו מריצים פקודה כלשהי ואת הפלט אנו רוצים לפתוח ישירות ב vscode, אז כדי לחסוך את העתבק אפשר פשוט לשרשר את המידע לvscode בצורה הבאה
$ k get pod/lala -o yaml | code -
כעת העורך מחבר את הstdin לפקודה והתוכן אפילו יכול להתעדכן בזמן אמת(לא לשכוח Ctrl+C כשרוצים לסגור את החיבור)
$ journalctl -f | code -
#clipboard#vscode
#code
#stdin
@bash_tips
לרזלב בלי hosts
רמת קושי: #advanced
כל מפתח ואיש סיסטם מכיר את הקובץ /etc/hosts, זהו בעצם הקובץ בו המערכת מחפשת כתובת אינטרנט כלשהיא לפני שהיא פונה החוצה לחפש את הכתובת בשרתי DNS השונים
לצורך התרגיל נריץ לרגע שרת פייתון מקומי בפורט 4444 ונגדיר לו כתובת אינטרנט בקובץ /etc/hosts
הרצת שרת פייתון
כעת כל פניה בדפדפן לכתובת 127.0.0.1:4444 תפנה אל התוכן שיש במיקום ממנו הרצנו את השרת
הגדרת כתובת אינטרנט מקומית לשרת
במידה ונגדיר בקובץ /etc/hosts שכתובת האתר החמוד שהקמנו היא
ובשביל להוכיח שזה באמת עובד ניתן להריץ בקשת אינטרנט בעזרת curl
אין מילים, מדהים לחלוטין
עד לכאן ההקדמה וכעת לטיפ
לא מעט פעמים כל שנרצה הוא רק לוודא שהשירות שלנו מגיב לכתובת האינטרנט שהגדרנו בקוד למרות שאין לנו רשומת DNS קיימת, והצורך להוסיף את הכתובת לקובץ /etc/hosts סתם יוצר סרבול של התהליך
ישנה אופציה קלילה יותר לשייך כתובת אינטרנט לip בצורה זמנית והיא על ידי שימוש ב curl עם הדגל --resolve ולהעביר לו את הביטוי שמחולק בצורה הבאה לשם האתר:מספר הפורט:כתובת הIP
ולאחר מכן פניה לכתובת שהגדרנו כאילו זהו שם האתר, במקרה שלנו זה יראה כך
כעת הפניה של curl תחזיר לנו את המידע מהשירות שלנו על פי כתובת האינטרנט הזמנית שהגדרנו, למרות שהכתובת לא מופיעה בקובץ ה hosts
#curl
#hosts
#server
#resolve
@bash_tips
רמת קושי: #advanced
כל מפתח ואיש סיסטם מכיר את הקובץ /etc/hosts, זהו בעצם הקובץ בו המערכת מחפשת כתובת אינטרנט כלשהיא לפני שהיא פונה החוצה לחפש את הכתובת בשרתי DNS השונים
לצורך התרגיל נריץ לרגע שרת פייתון מקומי בפורט 4444 ונגדיר לו כתובת אינטרנט בקובץ /etc/hosts
הרצת שרת פייתון
$ python3 -m http.server 4444
כעת כל פניה בדפדפן לכתובת 127.0.0.1:4444 תפנה אל התוכן שיש במיקום ממנו הרצנו את השרת
הגדרת כתובת אינטרנט מקומית לשרת
במידה ונגדיר בקובץ /etc/hosts שכתובת האתר החמוד שהקמנו היא
my.website
והיא משוייכת לכתובת הפנימית של המחשב 127.0.0.1
, אז כל פניה בדפדפן לכתובת my.website
בפורט 4444 תפנה ישירות לאתר המקומי שלנו
$ site="127.0.0.1 my.website"
$ echo "$site" | sudo tee -a /etc/hosts
ובשביל להוכיח שזה באמת עובד ניתן להריץ בקשת אינטרנט בעזרת curl
$ curl my.website:4444
...
<li><a href=".git/">.git/</a></li>
<li><a href=".gitmodules">.gitmodules</a></li>
<li><a href="Dockerfile">Dockerfile</a></li>
...
אין מילים, מדהים לחלוטין
עד לכאן ההקדמה וכעת לטיפ
לא מעט פעמים כל שנרצה הוא רק לוודא שהשירות שלנו מגיב לכתובת האינטרנט שהגדרנו בקוד למרות שאין לנו רשומת DNS קיימת, והצורך להוסיף את הכתובת לקובץ /etc/hosts סתם יוצר סרבול של התהליך
ישנה אופציה קלילה יותר לשייך כתובת אינטרנט לip בצורה זמנית והיא על ידי שימוש ב curl עם הדגל --resolve ולהעביר לו את הביטוי שמחולק בצורה הבאה לשם האתר:מספר הפורט:כתובת הIP
website_name:port:
ipולאחר מכן פניה לכתובת שהגדרנו כאילו זהו שם האתר, במקרה שלנו זה יראה כך
$ curl --resolve \
my.website:4444:127.0.0.1 \
my.website:
4444כעת הפניה של curl תחזיר לנו את המידע מהשירות שלנו על פי כתובת האינטרנט הזמנית שהגדרנו, למרות שהכתובת לא מופיעה בקובץ ה hosts
#curl
#hosts
#server
#resolve
@bash_tips
👍4
להעתיק
רמת קושי: #beginners
בלא מעט מערכות יש כלי שורת הפקודה שמאפשר להעתיק פלט בטרמינל ישירות לתוך ה clipboard.
בווינדוס למשל ניתן להשתמש ב clip
משתמשי זיש יכולים להשתמש בפקודת clipcopy
לשם כך כל שנצטרך הוא להשתמש בפקודת tee כדי לפצל את הפלט למספר מקורות וכעת ביטוי ה alias שלנו יראה כך
#copy
#xclip
#clipboard
@bash_tips
רמת קושי: #beginners
בלא מעט מערכות יש כלי שורת הפקודה שמאפשר להעתיק פלט בטרמינל ישירות לתוך ה clipboard.
בווינדוס למשל ניתן להשתמש ב clip
c:\> dir | clipובמאק יש את פקודת pbcopy
$ echo bla bla bla | pbcopyמה קורה אם כך בלינוקס?
משתמשי זיש יכולים להשתמש בפקודת clipcopy
$ cat ~/.ssh/id_rsa.pub| clipcopyמשתמשי באש לעומת זאת שרוצים לממש יכולת דומה צריכים להגדיר את ה alias הבא (שזה אגב בדיוק מה שעושה זיש)
$ alias clipcopy="xclip -selection clipboard"בגלל שאנו מגדירים לעצמנו את הקיצור הזה יתכן ונרצה לשנות מעט את ההתנהגות של הכלי, במקום שהעתקה תתבצע כמו בשאר הכלים ולא תדפיס לנו למסך שום פלט, יש לנו אפשרות להגדיר שבנוסף לפעולת העתקה של התוכן לקליפבורד, שהתוכן יודפס גם למסך ככה שיהיה קל לראות מה הועתק.
לשם כך כל שנצטרך הוא להשתמש בפקודת tee כדי לפצל את הפלט למספר מקורות וכעת ביטוי ה alias שלנו יראה כך
$ alias clipcopy="tee >(xclip -selection clipboard)"נ.ב. בכל מה שקשור ללינוקס ישנה תלות של כלי xclip שצריך להיות מותקן במערכת
#copy
#xclip
#clipboard
@bash_tips
👍3
לטעון סביבה
רמת קושי: #advanced
קובץ שמוכר בעולם ה ops הוא .env מדובר על קובץ שבגדול מכיל רשימה של משתני סביבה בהם הסביבה מאותחלת, מספר כלים כדוגמת docker-compose מכירים בקובץ ויודעים לטעון אותו לבד, מה קורה כשאנו רוצים לטעון קובץ .env ישירות לטרמינל?
דוגמה לקובץ .env
מחשבה ראשונה זה לעשות
נוכל לראות זאת בדוגמה שלהלן
להלן 2 דרכים מעניינות לפתרון
פתרון אפשרי, export
מה שקורה כאן הוא שפקודת
פתרון אפשרי נוסף allexport
בגדול מדובר על הפעלה של flag allexport, האופציה הזאת מעבירה לexport את רצף המשתנים ובעצם מאפשרת לפקודת
בכדי לראות שהמשתנים שלנו אכן נטענו לסביבה ניתן לבדוק זאת על ידי פקודת
#env
#export
#source
#variable
#env_variable
#session
@bash_tips
רמת קושי: #advanced
קובץ שמוכר בעולם ה ops הוא .env מדובר על קובץ שבגדול מכיל רשימה של משתני סביבה בהם הסביבה מאותחלת, מספר כלים כדוגמת docker-compose מכירים בקובץ ויודעים לטעון אותו לבד, מה קורה כשאנו רוצים לטעון קובץ .env ישירות לטרמינל?
דוגמה לקובץ .env
$ cat .env
APP_NAME=mytest
DEPLOYMENT_MODE=true
BUNDLE=test
...
מחשבה ראשונה זה לעשות
source
לקובץ ולטעון אותו, העניין הוא שהכרזת משתנים בלי הפקודה export
תטען את המשתנים לסשן של הטרמינל, כל סקריפט שנריץ מאותו הסשן לא יקבל את המשתנים שבקובץ כי הוא רץ בסשן משל עצמו (דברנו על זה מעט בעבר).נוכל לראות זאת בדוגמה שלהלן
$ source .env
$ cat test.sh
#!/bin/bash
declare -p APP_NAME DEPLOYMENT_MODE BUNDLE
$ bash test.sh
test.sh: line 2: declare: APP_NAME: not found
test.sh: line 2: declare: DEPLOYMENT_MODE: not found
test.sh: line 2: declare: BUNDLE: not found
להלן 2 דרכים מעניינות לפתרון
פתרון אפשרי, export
export $(grep -v '^#' .env)
מה שקורה כאן הוא שפקודת
export
יודעת להגדיר מספר משתנים בו זמנית, grep
מחריג כל שורה שהיא הערה וכך טוען רק את המשתנים, אפשר כמובן לשפר את החלק האחרון אבל הרעיון במקומו.פתרון אפשרי נוסף allexport
set -a
source .env
set +a
בגדול מדובר על הפעלה של flag allexport, האופציה הזאת מעבירה לexport את רצף המשתנים ובעצם מאפשרת לפקודת
source
לטעון את כל המידע שבקובץ, אנו מכבים את האופציה לאחר שטענו את הסביבה.בכדי לראות שהמשתנים שלנו אכן נטענו לסביבה ניתן לבדוק זאת על ידי פקודת
env
שמציגה בעצם את כל המשתנים של הסביבה בה אנו עובדים.#env
#export
#source
#variable
#env_variable
#session
@bash_tips
👍19🔥5
Forwarded from לומדים לינוקס
לקפוץ מעל jumpbox
בלא מעט מערכות יש נוהל אבטחה שאין גישת ssh ישירה לשרת, אלא יש מכונה אחת שמורשת להתחבר לשרת ב ssh וכל מי שרוצה להתחבר לשרת צריך לעבור דרך המכונה הזאת, המושג הזה ברשת מוכר בשם מכונת jumpbox
אוקי אז יש לנו מכונה jumpbox ואנו רוצים להתחבר אליה, המסלול שנצטרך לעבוד הוא כזה
1. העתקה של המפתח הציבורי שלנו למכונת ה jumpbox
2. העתקת מפתח של מכונת ה jumpbox לשרת אליו אנו רוצים להתחבר
ואז לבצע את אותה הדרך עם חיבורי ssh
התחברות ssh לשרת ה jumpbox
התחברות נוספת משרת הjumpbox לשרת
נשמע ארוך לא?
במקום זאת אפשר להשתמש בתכונה של ssh ולהגדיר לו רצף של מכונות שבכולן הוא ישתמש באותו מפתח פרטי כדי להזדהות במידה ויש לנו מפתח ציבורי במכונה נוכל להמשיך למכונת היעד, זה נראה כך
אנו משתמשים בדגל -J כדי להכריז מהי מכונת ה jumpbox שלנו, ולאחר מכן לאיזה שרת אנו רוצים להתחבר דרכה, ssh הולך למכונה הראשונה מכונת ה jumpbox ומנסה למצוא התאמה בין המפתח הציבורי שנמצא במכונה למפתח הפרטי שנמצא אצלנו על המחשב
במידה והמפתח הציבורי שלנו נמצא במכונה, ssh יעבור למכונה הבאה דרך מכונת ה jumpbox וינסה להתחבר ממכונת ה jumpbox לשרת, אם המפתח הציבורי שלנו נמצא גם על השרת ssh יבדוק התאמה של המפתח הציבורי מול המפתח הפרטי שנמצא על המחשב שלנו ונוכל לעבוד על השרת בצורה "ישירה"
#ssh
#jumpbox
@learnlinuxnote
בלא מעט מערכות יש נוהל אבטחה שאין גישת ssh ישירה לשרת, אלא יש מכונה אחת שמורשת להתחבר לשרת ב ssh וכל מי שרוצה להתחבר לשרת צריך לעבור דרך המכונה הזאת, המושג הזה ברשת מוכר בשם מכונת jumpbox
אוקי אז יש לנו מכונה jumpbox ואנו רוצים להתחבר אליה, המסלול שנצטרך לעבוד הוא כזה
1. העתקה של המפתח הציבורי שלנו למכונת ה jumpbox
2. העתקת מפתח של מכונת ה jumpbox לשרת אליו אנו רוצים להתחבר
ואז לבצע את אותה הדרך עם חיבורי ssh
התחברות ssh לשרת ה jumpbox
התחברות נוספת משרת הjumpbox לשרת
נשמע ארוך לא?
במקום זאת אפשר להשתמש בתכונה של ssh ולהגדיר לו רצף של מכונות שבכולן הוא ישתמש באותו מפתח פרטי כדי להזדהות במידה ויש לנו מפתח ציבורי במכונה נוכל להמשיך למכונת היעד, זה נראה כך
ssh -J myuser@jumpbox myuser@isolated.server
אנו משתמשים בדגל -J כדי להכריז מהי מכונת ה jumpbox שלנו, ולאחר מכן לאיזה שרת אנו רוצים להתחבר דרכה, ssh הולך למכונה הראשונה מכונת ה jumpbox ומנסה למצוא התאמה בין המפתח הציבורי שנמצא במכונה למפתח הפרטי שנמצא אצלנו על המחשב
במידה והמפתח הציבורי שלנו נמצא במכונה, ssh יעבור למכונה הבאה דרך מכונת ה jumpbox וינסה להתחבר ממכונת ה jumpbox לשרת, אם המפתח הציבורי שלנו נמצא גם על השרת ssh יבדוק התאמה של המפתח הציבורי מול המפתח הפרטי שנמצא על המחשב שלנו ונוכל לעבוד על השרת בצורה "ישירה"
#ssh
#jumpbox
@learnlinuxnote
👍10
להטמיע בינרי בסקריפט באש
רמת קושי: #advanced
לא מזמן יצא לי להיתקל בסקריפט התקנה של AnyConnect והיה שם רעיון חביב ודיי פשוט האמת לאיך ליצור סקריפט בודד שמכיל בתוכו מספר קבצים, גם כאלו שהם בינריים.
בשני מילים הרעיון בכללותו הוא להגדיר עוגן איפשהו בסקריפט ולהחליט שמכאן והלאה התוכן הוא בינרי, ואז להגדיר בסקריפט לקחת את המידע שנמצא מתחת לאותו העוגן ולעבוד איתו.
כעת נראה איך הרעיון יכול להיות ממומש הלכה למעשה
לצורך העניין כך נראה הסקריפט שלנו
מה שקורה כאן הוא כך
שורה 3: עוברת על כל הסקריפט ומחפשת את העוגן שהגדרנו, במקרה שלנו העוגן נמצא בשורה 9, ARCHIVE_HERE, למי שלא מכיר פרמטר $0 הוא בעצם שם הסקריפט
שורה 5: לאחר שאנו יודעים מאיזה שורה מתחיל התוכן הבינרי, אנו שומרים רק את התוכן הבינרי לתוך משתנה, הדבר נעשה על ידי פקודת tail שקוראת תוכן מסוף הקובץ ומקבלת שורה ספציפית מהיכן לקרוא, התוכן עובר ל base64 במקרה שלנו ולכן נקודד אותו חזרה לתוכן רגיל, פקודת tar תציג לנו את המידע שהוטמע בפנים
שורה 9: זהו העוגן שהגדרנו
למה אנו צריכים הגדרה לשורה 7?
מה שקורה הוא שבגלל שאנו בסקריפט באש עשוי להתייחס לתוכן הבינרי או לעוגן כפקודה בפני עצמה, בכדי למנוע את השגיאה אנו יוצאים מהסקריפט לפני שבאש מריץ את המשך הקובץ.
אוקי נשמע נהדר, איך אנו מטעינים את הבינרי לסקריפט?
ניקח לדוגמה קובץ tar שמכיל את מבנה הקבצים הבא
ניתן להשתמש ב cat כדי לשפוך את התוכן הבינרי לקובץ אבל ישנם המון מקומות בהן התוכן עשוי להשתנות ולא להישאר נאמן למקור לכן נעדיף לעבוד עם base64
לפני שאנו מתקדמים הלאה אנו מוחקים בסקריפט את כל התוכן שמתחת לעוגן ומשאירים שורה ריקה
כעת מהטרמיל אנו מקודדים את הקובץ לbase64, ומשרשרים את הפלט לסוף הסקריפט זה נראה כך
אנו משתמשים באופרטור
כעת הרצה של הסקריפט תציג לנו את התוכן הבינרי שמוטמע בפנים
ניתן כמובן לשנות את שורה 5 וליצור קובץ ישירות מהתוכן שיוצר השחזור של ה base64
#tar
#binary
#base46
#scripting
@bash_tips
רמת קושי: #advanced
לא מזמן יצא לי להיתקל בסקריפט התקנה של AnyConnect והיה שם רעיון חביב ודיי פשוט האמת לאיך ליצור סקריפט בודד שמכיל בתוכו מספר קבצים, גם כאלו שהם בינריים.
בשני מילים הרעיון בכללותו הוא להגדיר עוגן איפשהו בסקריפט ולהחליט שמכאן והלאה התוכן הוא בינרי, ואז להגדיר בסקריפט לקחת את המידע שנמצא מתחת לאותו העוגן ולעבוד איתו.
כעת נראה איך הרעיון יכול להיות ממומש הלכה למעשה
לצורך העניין כך נראה הסקריפט שלנו
$ cat -n /tmp/installer.sh
1 #!bin/bash
2
3 binary_content=$(awk '/^ARCHIVE_HERE/ {print FNR + 1}' $0)
4
5 tail -n+$binary_content $0 | base64 -d | tar -ztv
6
7 exit 0
8
9 ARCHIVE_HERE
10
מה שקורה כאן הוא כך
שורה 3: עוברת על כל הסקריפט ומחפשת את העוגן שהגדרנו, במקרה שלנו העוגן נמצא בשורה 9, ARCHIVE_HERE, למי שלא מכיר פרמטר $0 הוא בעצם שם הסקריפט
שורה 5: לאחר שאנו יודעים מאיזה שורה מתחיל התוכן הבינרי, אנו שומרים רק את התוכן הבינרי לתוך משתנה, הדבר נעשה על ידי פקודת tail שקוראת תוכן מסוף הקובץ ומקבלת שורה ספציפית מהיכן לקרוא, התוכן עובר ל base64 במקרה שלנו ולכן נקודד אותו חזרה לתוכן רגיל, פקודת tar תציג לנו את המידע שהוטמע בפנים
שורה 9: זהו העוגן שהגדרנו
למה אנו צריכים הגדרה לשורה 7?
מה שקורה הוא שבגלל שאנו בסקריפט באש עשוי להתייחס לתוכן הבינרי או לעוגן כפקודה בפני עצמה, בכדי למנוע את השגיאה אנו יוצאים מהסקריפט לפני שבאש מריץ את המשך הקובץ.
אוקי נשמע נהדר, איך אנו מטעינים את הבינרי לסקריפט?
ניקח לדוגמה קובץ tar שמכיל את מבנה הקבצים הבא
$ tar -tvf installer.tar
installer/
installer/req_list
installer/installer.db
installer/execfile
ניתן להשתמש ב cat כדי לשפוך את התוכן הבינרי לקובץ אבל ישנם המון מקומות בהן התוכן עשוי להשתנות ולא להישאר נאמן למקור לכן נעדיף לעבוד עם base64
לפני שאנו מתקדמים הלאה אנו מוחקים בסקריפט את כל התוכן שמתחת לעוגן ומשאירים שורה ריקה
9 ARCHIVE_HERE
10
כעת מהטרמיל אנו מקודדים את הקובץ לbase64, ומשרשרים את הפלט לסוף הסקריפט זה נראה כך
$ base64 installer.tar >> installer.sh
אנו משתמשים באופרטור
>>
כדי להוסיף את התוכן לסוף הקובץ ולכן השורה הריקה שהשארנו מקודם תתמלא בתוכן החדשכעת הרצה של הסקריפט תציג לנו את התוכן הבינרי שמוטמע בפנים
$ bash installer.sh
installer/
installer/req_list
installer/installer.db
installer/execfile
ניתן כמובן לשנות את שורה 5 וליצור קובץ ישירות מהתוכן שיוצר השחזור של ה base64
#tar
#binary
#base46
#scripting
@bash_tips
👍12🔥2
טיפ קצר וחביב להתנהלות בטרמינל
רמת קושי: #beginners
לא מעט פעמים יוצא שאנו עורכים איזו פקודה שאנו רוצים להריץ ואז נזכרים שצריך לבצע איזו פעולה קודם לכן, אממה אנו רוצים שהפקודה שערכנו תישאר בהיסטוריה ולא שנצטרך לערוך אותה שוב.
לשם כך ישנו הקיצור
#terminal
#shortcuts
#comments
@bash_tips
רמת קושי: #beginners
לא מעט פעמים יוצא שאנו עורכים איזו פקודה שאנו רוצים להריץ ואז נזכרים שצריך לבצע איזו פעולה קודם לכן, אממה אנו רוצים שהפקודה שערכנו תישאר בהיסטוריה ולא שנצטרך לערוך אותה שוב.
לשם כך ישנו הקיצור
Alt + Shift + #
שכל מה שהוא עושה זה לקחת את הפקודה שרשמנו ולהריץ אותו כהערה כך שלאחר מכן ניתן יהיה לשלוף את ההערה מההיסטוריה ולהריץ אותה כפקודה.#terminal
#shortcuts
#comments
@bash_tips
👍23