תרגול מס' 7
description
Transcript of תרגול מס' 7
7תרגול מס' -כתיבת תסריטים בC-Shell-בקרת תהליכים בUnix
2מבוא לתכנות מערכות - 234122
תסריטיםהרצת תסריטים-מבני בקרה בC-Shellדוגמאות השוואה ביןC-ו C-Shell
3מבוא לתכנות מערכות - 234122
אוטומטיזציה נניח )מקרה היפותטי לחלוטין( שברשותנו קבצי בדיקה ופלט לתכנית שלנו
וברצוננו לבדוק את נכונות התכנית מול קבצים אלו
פקודות לכל בדיקה3צריך לכתוב
גם עם שימוש במנגנון ההיסטוריה הרצת הבדיקותמעיקה ולוקחת הרבה זמן מיותר
:תסריט של הרצת הפקודות. ניצור קובץ אשר יכיל "אוטומטיזציההפתרון "לפיו יורצו כל הפקודות לפי הסדר
> (mtm_checkout < test1.in >! tmpout) >&! tmperr> diff expout1 tmpout> diff experr1 tmperr
4מבוא לתכנות מערכות - 234122
sourceהרצת תסריט בעזרת ניתן להריץ קובץ המכיל פקודותC-Shell להלן( - תסריטscript על ידי )
sourceהפקודה -הפקודות יבוצעו בShell כאילו נכתבו בשורת הפקודה אחת אחרי הנוכחי
השניהecho Running test 1(mtm_checkout < test1.in >! tmpout) >&! tmperrdiff expout1 tmpoutdiff experr1 tmperrecho Running test 2(mtm_checkout < test2.in >! tmpout) >&! tmperrdiff expout1 tmpoutdiff experr1 tmperrecho Running test 3(mtm_checkout < test3.in >! tmpout) >&! tmperrdiff expout1 tmpoutdiff experr1 tmperr
run_tests> source run_testsRunning test 1Running test 2Running test 3
5מבוא לתכנות מערכות - 234122
תסריטי אתחול בהתחברות של משתמש למערכת מורץ התסריט.login אשר בתיקית
הבית של המשתמש בפתיחתC-Shell חדש מורץ התסריט .cshrc הרצות תסריטי האתחול מתבצעות באמצעותsource ולכן הן משפיעות ,
Shellעל מצב ה-
set path = ($path .)set savehist=1000alias ll ls -lalias cdex2 cd ~mtm/public/1011a/ex2alias GCC gcc-std=c99 -Wall \
-pedantic-errors -Werror
.cshrc# welcome messageecho ------ Welcome `whoami` !-------- echo You are in `pwd` directory of \ `hostname`echo OS is `uname -s`# echo disk usage is `du -sh | cut -f1`echo `who | wc -l` users are logged inecho Today is `date`
.login
6מבוא לתכנות מערכות - 234122
הרצת תסריט כקובץ הרצה:ניתן להריץ תסריט כפקודה
התסריט יש להוסיף את השורהבתחילת–#!/bin/tcsh -f
שהשורה הראשונה בקובץ מגדירה את התכנית לביצוע Unix מסמן ל-#!•שאר הפקודות בקובץ
•/bin/tcsh הוא שם התכנית לביצוע הפקודות, במקרה שלנוC-Shell•-f -מונע מהShellלהריץ תסריטי אתחול
בנוסף יש להוסיף הרשאת ריצה לקובץ–כעת ניתן להריץ את התסריט כמו תכנית רגילה–
בניגוד להרצה באמצעות פקודתsourceתהליך התסריט יבוצע בShell אשר יסתיים בסוף ריצת התסריטחדש
7מבוא לתכנות מערכות - 234122
הרצת תסריט כקובץ הרצה:נמיר את תסריט הרצת הבדיקות שלנו לקובץ הרצה
התסריטבעיה חדשה :מתחיל להסתבך, הוספתבדיקות נוספות משכפלת
קוד בתסריט ולא נוחה )ייתכנו אלפי בדיקות(נשתמש במבני בקרה )תנאים ולולאות( בדומה לשפת פתרון :C
#!/bin/tcsh -fecho Running test 1(mtm_checkout < test1.in >! tmpout) >&! tmperrdiff expout1 tmpoutdiff experr1 tmperrecho Running test 2(mtm_checkout < test2.in >! tmpout) >&! tmperrdiff expout1 tmpoutdiff experr1 tmperrecho Running test 3(mtm_checkout < test3.in >! tmpout) >&! tmperrdiff expout1 tmpoutdiff experr1 tmperr
run_tests> chmod a+x run_tests> ./run_testsRunning test 1Running test 2Running test 3
8מבוא לתכנות מערכות - 234122
while ניתן ליצור לולאותwhile -בC-Shell:
while (<expression>)<command1><command2>...
end< ממשיך להתקייםexpressionהפקודות בגוף הלולאה יבוצעו כל עוד >– מהטרמינלישירות כמו שאר מבני הבקרה ניתנות לביצוע whileלולאות –
#!/bin/tcsh -fset i=1while ($i <= 3) echo Running test $i (mtm_checkout < test$i.in \ >! tmpout) >&! tmperr diff expout$i tmpout diff experr$i tmperrend
run_tests> ./run_testsRunning test 1Running test 2Running test 3
> set i=1> while ($i <= 3)while? echo $iwhile? @ i++while? end123
9מבוא לתכנות מערכות - 234122
foreach לולאתforeachמשמשת למעבר על רשימה בצורה נוחה
foreach <varname> (<list>)<command1><command2>...
end<varnameהוא שם המשתנה שיכיל בכל פעם איבר מהרשימה ><listהיא רשימה של מחרוזות >
#!/bin/tcsh -fforeach test (test*.in) echo Running $test (mtm_checkout < $test >! tmpout) >&! tmperr diff expout_$test tmpout diff experr_$test tmperrend
run_tests
> ./run_testsRunning test1.inRunning test2.inRunning test3.in
10מבוא לתכנות מערכות - 234122
if-ניתן להגדיר בC-Shellמשפטי תנאי בשתי גרסאות בשורה יחידה ללאelse:
if (<expression>) <command>-עם אפשרות ל( עבור בלוקים של פקודותelse:)
if (<expression>) then[commands]
[else[more commands] ]
endif
11מבוא לתכנות מערכות - 234122
while ו-if אפשריים ב-ביטויים ו-== על ידי מחרוזותהשוואת != על ידי ערכים מספריים השוואת>= ,<= ,> ,<
אם אחד הפרמטרים לאופרטור אינו ערך מספרי תתקבל שגיאה– התנאי-f <filename >בודק האם
<filenameקיים קובץ בשם > התנאי-d <filename >בודק האם
<filenameקיימת תיקיה בשם >עבור קדימויותסוגרייםניתן להשתמש ב ניתן להשתמש בפעולות חשבוניות על
/ ו-*, -, +ערכים מספריים כמו ניתן להשתמש באופרטורים לוגיים
! ו-&&, ||להרכבת תנאים
> set str1=Hello> if ($str1 == Hello) echo yes yes> if (7 < 20) echo yesyes> if (0 == 00) echo yes> if (0 <= 00) echo yesyes>if (-f a.txt) echo file exists> cat > a.txtHello world!> if (-f a.txt) echo file existsyes> mkdir mtm> if ( !(-f b.txt && -d mtm) ) echo yesyes
12מבוא לתכנות מערכות - 234122
התאמת מחרוזות מאפשר התאמת מחרוזת לתבנית~=האופרטור
הארגומנט השמאלי הוא מחרוזת רגילה–כמו ] [ ו-?, *אשר יכולה לכלול את הסימנים תבנית הארגומנט הימני הוא –
שתואר עבור תבניות של שמות קבצים
הוא השלילה של ~=~!האופרטור > if (ends_with_z =~ *[zZ]) echo matchmatch> if ("no point in string" !~ *.*) echo no pointno point> if ("point - . - in string" !~ *.*) echo no point> set file = test4.in> if ($file =~ test*.in) echo test filetest file
13מבוא לתכנות מערכות - 234122
switch ניתן ליצור מבנהswitch -בC-Shell:
switch (<string>) case <pattern1>: <cshell commands> [breaksw] ... case <pattern_n>: <cshell commands> [breaksw] [default: <cshell commands>]endsw
-הכללים בswitch תבניות מקבלים וההתאמה מתבצעת כמו עבור אופרטור ~=
אם כמה כללים מתאימים ייבחר הכלל שמתאיםהראשון
switch($c) case "[a-z]": echo small letter breaksw case "[A-Z]": echo big letter breaksw case "[0-9]": echo digit breaksw case '$': echo dollar sign breaksw default: echo neither letter nor digitendsw
14מבוא לתכנות מערכות - 234122
goto ניתן להשתמש במשפטיgoto-כמו ב C
goto <label>...<label>:...
שימוש במשפטיgoto ( ולא ללא קשר לשפת התכנות) הוא תכנות רענהוג להשתמש בהם
-השימוש בgoto "קשה להבנה יוצר קוד "ספגטי
15מבוא לתכנות מערכות - 234122
-כמו בCניתן לגשת לפרמטרים המועברים בשורת הפקודה לתסריט המשתנהargv מכיל את רשימת הפרמטרים לתסריט
–argv[1])הוא הפרמטר הראשון )ולא שם התסריט -דרך נוחה יותר לגשת לפרמטר הn
n$היא על ידי *$תוחלף ברשימת כל הפרמטרים
לתסריט$0תוחלף בשם התסריט
> echo_script aaa bbb ccccommand: echo_scriptparameter 1 : aaaparameter 2 : bbbparameter 3 : ccc
העברת פרמטרים בשורת הפקודה
#!/bin/tcsh -fecho command: $0set number = 1foreach param ( $* ) echo parameter $number : $param @ number++end
echo_script
איך ניתן לדעת את מספר הפרמטרים
שהתקבלו?
16מבוא לתכנות מערכות - 234122
קריאת קלט ניתן לקרוא שורה מהקלט הסטנדרטי על ידי<$ <$ על ידי יוחלףהביטוי C-Shell בשורת קלט שתיקלט מהקלט
הסטנדרטי
בד"כ נשתמש בסוגריים כדי לשמור את כל שורת הקלט< set line=$<Hello world> echo $lineHello< set line=($<)Hello world> echo $lineHello world
> set input=$<Hello> echo $inputHello
17מבוא לתכנות מערכות - 234122
עבודה עם קבצים-לא ניתן בC-Shell-לכתוב ולקרוא מקבצים בצורה ישירה כמו ב Cכדי לאפשר עבודה עם קבצים נשתמש בהפניות קלט/פלט ותסריטי עזר
> cat > file.txtThe dingo ate your baby> main_scriptThe first line is:The dingo ate your baby
#!/bin/tcsh -fcat file.txt | auxiliary_script
main_script
#!/bin/tcsh -fset line=($<)echo "The first line is:"echo "$line"
auxiliary_script
18מבוא לתכנות מערכות - 234122
חלוקה פונקציונלית של תסריטים
-מאחר ולא ניתן להגדיר פונקציות בC-Shell נחלק את הקוד שלנו בקבצים נפרדיםלתסריטים שונים
-שימו לב שניתן להשתמש בC-Shell כדי לערבב תסריטים עם תכניות בקלות - מכאן מגיע כוחן של שפות תסריטים - בשפות שונות שנכתבו
scripting languagesניתן להעביר פרמטרים לתסריטי עזר
בעזרת פרמטרים בשרות הפקודה–pipelineבעזרת –בעזרת קבצים זמניים–
ניתן לקבל ערכים חזרה מתסריטי עזרבעזרת פלט מתסריט העזר–
19מבוא לתכנות מערכות - 234122
העברת והחזרת ערכים העברת פרמטרים לתסריטי עזר
יכולה להתבצע בדרכים הבאותשורת הפקודהב–
helper_script $arg1 $arg2
pipelineבעזרת –echo $arg1 $arg2 | helper_script
דרך קובץ זמני–echo $arg1 $arg2 > temphelper_script < temp
החזרת ערכים מתסריטי העזריכולה להתבצע בעזרת
backticksשימוש ב-–set result = `helper_script`
pipelineהעברה לתסריט אחר ב-–helper_script | another_script
דרך קובץ זמני–helper_script > temp
20מבוא לתכנות מערכות - 234122
דוגמה נתון קובץ בשםfootball.txt המכיל
נתונים על שערים שהובקעו במשחקי כדורגל
,כל שורה בקובץ מציינת שם של שחקןמספר השערים שהבקיע במשחק
שנערך בתאריך מסוים, שם הקבוצה בה הוא שיחק ושם הקבוצה היריבה
ברצוננו לכתוב תסריט בשםplayer אשר יקבל כפרמטר שם של שחקן
וידפיס את כל השורות עבורו ואת סכוםfootball.txtמהקובץ
מספר השערים שהבקיע
Alon Miz. 2 23/10/93 Macabi-Haifa Macabi-Tel-AvivIzak Zoh. 1 12/11/93 Macabi-Tel-Aviv Hapoel-Beer-ShevaRonen Ha. 3 27/12/93 Hapoel-Tel-Aviv Macabi-Tel-AvivReuven A. 2 12/11/93 Macabi-Haifa Hapoel-Tel-AvivEyal Ber. 1 20/11/93 Macabi-Haifa Macabi-Tel-Aviv Izak Zoh. 1 12/11/93 Macabi-Tel-Aviv Hapoel-HaifaAlon Miz. 2 26/10/93 Macabi-Haifa Beitar-JerusalemIzak Zoh. 2 12/12/93 Macabi-Tel-Aviv Macabi-HiafaAlon Miz. 2 23/12/93 Macabi-Haifa Macabi-Pet-TikvaRonen Ha. 3 27/11/93 Hapoel-Tel-Aviv Macabi-Haifa
football.txt
> player "Alon Miz."Alon Miz. 2 23/10/93 Macabi-Haifa Macabi-Tel-AvivAlon Miz. 2 26/10/93 Macabi-Haifa Beitar-JerusalemAlon Miz. 2 23/12/93 Macabi-Haifa Macabi-Pet-TikvaTotal number of goals: 6
21מבוא לתכנות מערכות - 234122
פתרון לא נוכל לקרוא את הקובץfootball.txt
ולכן ניעזר בתסריט עזרplayerישירות מתוך
ניצור את התסריטcalc_totalאשר יקבל את השורות הרלוונטיות לשחקן וידפיס את
השורות וסכום השערים
#!/bin/tcsh -fgrep "$1" football | calc_total
player
#!/bin/tcsh -fset line = ($<)set sum = 0while ($#line != 0) @ sum = $sum + $line[3] echo $line set line = ($<)endecho "total number of goals: $sum"
calc_total
התבנית הכללית של עיבוד קלט
התבנית הכללית של עיבוד קלט
התבנית הכללית של עיבוד קלט
22מבוא לתכנות מערכות - 234122
דוגמה נוספת כתבו תסריט לדירוג שחקנים בשםscores אשר יקבל רשימה של שמות
שחקנים בשורת הפקודה וידפיס את דירוג השחקנים לפי מספר הגולים שהבקיעו
לכל שחקן יש להדפיס את דירוגו, שמו ומספר הגולים שהבקיע–שני שחקנים שהבקיעו מספר זהה של גולים יקבל דירוג זהה–יש להדפיס את השחקנים ממוינים בדר יורד לפי מספר הגולים שהבקיעו–
> scores "Alon Miz." "Izak Zoh." "Ronen Ha." "Reuven A."1 Alon Miz. 61 Ronen Ha. 62 Izak Zoh. 43 Reuven A. 2
23מבוא לתכנות מערכות - 234122
פתרון#!/bin/tcsh -f@ i = 1while ( $i <= $#argv ) grep "$argv[$i]" football.txt | calc_score >>! temp @ i++endsort -nrk3 temp | add_ranksif (-f temp) rm -f temp
scores
#!/bin/tcsh -fset line = ($<)set sum = 0set player_name = ($line[1-2])while ($#line != 0) @ sum += $line[3] set line = ($<)endecho $player_name $sum
calc_score#!/bin/tcsh -fset line = ($<)set place = 1@ goals = $line[3]while ($#line != 0) if ($goals != $line[3]) then @ place++ @ goals = $line[3] endif echo $place $line set line = ($<)end
add_ranks
24מבוא לתכנות מערכות - 234122
C ל-C-Shellהשוואה בין C-Shell שפת תסריטים היא -scripting language
.Perl, Tcl, Python, Rubyשפות תסריטים נוספות: –
C שפת תכנות מערכת היא -system programming language#.C++, Java, Cשפות מערכת נוספות: –
25מבוא לתכנות מערכות - 234122
C ל-C-Shellהשוואה בין של יתרונות C-Shell על C:
מחרוזות ומשתניםעבודה נוחה עם –" תכניות קיימותלהדביקנוח "– משמעותית לחלק מהמשימותקצרקוד –על דברים לא צריך להכריז אין קומפיילר -–
של חסרונות C-Shell לעומת C:אין בדיקותאין קומפיילר - –
מאפשר באגים מסוכנים)לעתם פי כמה מאות( איטית–
-נבחר בC-Shell מטלות פשוטות וקצרות שזמן הביצוע שלהן לא עבורקריטי
set deposits = ($*)set account_balance = 100foreach d ($deposits) @ acount_balance=$account_balance + $dendecho $account_balance
26מבוא לתכנות מערכות - 234122
C-Shellסיכום - כדי לחסוך ביצוע חוזר וידני של פעולות ניתן ליצור תסריטים המכילים
או הפיכתם לקובץ הרצהsourceרצף פקודות שימושי ולהריצם בעזרת -בC-Shell קיימים מבני הבקרה while, foreach, if-ו switch המאפשרים
כתיבת קוד מתקדם בתסריטים-ניתן לגשת לפרמטרים לשרות הפקודה של תסריט בדומה לתכנית בC-כדי לקרוא מהקלט הסטנדרטי בC-Shell<$-נשתמש ב -כדי לקרוא מקובץ בC-Shell-נשתמש בתסריטי עזר ו pipelineכתיבת תסריטים מסתמכת על הדבקת תסריטים ופקודות שונות-נשתמש בC-Shell ,עבור מטלות פשוטות שאינן דורשות חישובים רבים
Cעבור שאר המטלות נמשיך להשתמש ב-
27מבוא לתכנות מערכות - 234122
Unixבקרת תהליכים ב-הרצה בחזית וברקע
28מבוא לתכנות מערכות - 234122
Unixריבוי תהליכים ב-Unix( היא מערכת הפעלה התומכת בריבוי תהליכים multi-tasking)
חובה עבור מערכת שנועדה לשירות מספר רב של משתמשים בו זמנית–
תהליך הוא הרצה של תכנית כלשהיניתן להריץ תכנית יחידה במספר תהליכים במקביל–
בניגוד למנשק גרפי בו השליטה במספר תהליכים אינטואיטיבית עבורעבודה בטרמינל יש להכיר מספר פקודות וקיצורים
29מבוא לתכנות מערכות - 234122
הרצה בחזית וברקעShellיחיד יכול להריץ מספר תהליכים בו זמנית
כל התהליכים מדפיסים את הפלט שלהם לערוצי הפלט הסטנדרטיים–רק תהליך אחד יכול להשתמש בערוץ הקלט הסטנדרטי–
רץ בחזיתתהליך אשר מקושר לערוץ הקלט הסטנדרטיכדי להריץ תהליך בחזית יש להפעילו כרגיל–
> command ולא ניתן להכניס פקודות חדשותpromptכל עוד תהליך רץ בחזית אין גישה ל-–
רצים ברקעתהליכים שאינם מקושרים לקלט הסטנדרטיניתן להריץ תהליך ברקע על ידי הוספת & לסוף הפקודה–
> command & במצב זה התהליך אינו רץ אך מצבו נשמר בזיכרון ונוכל מושההתהליך יכול להיות גם ,
להמשיך את הרצתו כשנרצה
30מבוא לתכנות מערכות - 234122
בדיקת מצב תהליכים הפקודהjobs-מדפיסה את רשימת התהליכים המורצים תחת ה Shell
> jobsלכל תהליך מוצג מספר מזהה, מצבו ושם הפקודה-מייצג את התהליך "הנוכחי"+סימן ה
תהליך זה יהווה את ברירת המחדל לפקודות טיפול בתהליכים–-מייצג את התהליך הבא בתור להיות +-סימן ה
#!/bin/tcsh -fwhile ( 1 ) sleep 1 echo Loop $1!end
loop> ./loop 1 &[1] 3692> Loop 1!./loop 2 &[2] 3711Loop 2!Loop 1!
כאשר מספר תהליכים מוציאים פלט בו זמנית
הטרמינל מתבלגן במהירות
המספר בסוגריים המרובעים הוא מספר
Shellהתהליך תחת ה-
31מבוא לתכנות מערכות - 234122
שליחת אותות לתהליך בחזית כדי לשנות את מצב הריצה של התהליך הרץ בחזית ניתן לשלוח אותות
בעזרת קיצורים מהמקלדת
Ctrl+Cהורג )מפסיק( את התהליך אשר בחזית :
Ctrl+Zמשהה את התהליך אשר בחזית :התהליך מפסיק לרוץ אך מצבו נשמר–
32מבוא לתכנות מערכות - 234122
פקודות לניהול תהליכים ניתן להחזיר תהליך לריצה בחזית בעזרתfg
> fg [process] ניתן להחזיר תהליך לריצה ברקע בעזרתbg
> bg [process] ניתן להשהות תהליך על ידיstop
> stop <process> ניתן להרוג תהליך על ידי הפקודהkill
> kill <process>% ניתן לציין מספר תהליך ע"י –<str%>< ע"י strניתן להריץ את התהליך ששמו מתחיל ב->–
אם קיימים שני תהליכים מתאימים הפקודה תיכשל•+: אם לא צוין מספר תהליך יוחזר התהליך שמסומן ב-bg ו-fgעבור –
33מבוא לתכנות מערכות - 234122
- סיכוםUnixבקרת תהליכים ב-
ריצה בחזית מושהה
ריצה ברקע מופסק
Ctrl+Z
fg
fg
kill
kill
Ctrl+C bg
stop
הרצה רגילה
& הרצה עם