דוגמא ל Daemon ב Java
description
Transcript of דוגמא ל Daemon ב Java
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
JavaJava ב ב DaemonDaemonדוגמא ל דוגמא ל
אליהו חלסצ'י
89-21189-211 22תכנות מתקדם תכנות מתקדם 10תרגול מספר
2009-2010תש"ע
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
הקדמהבשיעור שעבר ראינו כיצד ניתן להריץ תוכנית •
java כ service תחת windows.
שהריצה native כתוכנית tomcatהשתמשנו ב •JVM.ובתוכה התוכנית שלנו
עבור Daemonבשיעור זה נלמד כיצד לייצר • )לינוקס(Unix שלנו – תחת javaתוכנית ה
ubuntu 9.04התוכניות בתרגול נכתבו תחת •
גם הפעם ברצוננו ליצור תהליך מנותק שרץ •ברקע ללא התערבותנו הישירה.
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
Daemonכיצד נוצר )(forkתחילה נעשה שימוש ב •
יוצר העתק )הילד( של התהליך שלנו )ההורה(.forkה – )אב כל Initניתן להורה לסיים, והילד יעבור להיות תחת –
התהליכים(.התוצאה: תהליך הילד מנותק לחלוטין מתהליך האב –
וממשיך לרוץ ברקע כעצמאי.
נאתחל את הרשאות התהליך ע"פ הצורך ע"י •umask)( )user mask(
signalsהתהליך שלנו עדיין יכול לקבל •מההורה המקורי או מהחברים באותה קבוצת
.)(setsidתהליכים, לכן נרצה לנתק אותו ע"י
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
Daemonכיצד נוצר כדי)(chdir ע"י directoryנרצה לשנות את ה •
שנפעל מתוך אחת מוכרת )ההפך עלול לגרום לבעיות(–או אחת המתאימה לריצת התהליך שלנו )לדוג' –
chdir)“/servers/”()
שאולי ירשנו ובהםDescriptorsנרצה לסגור •–stdin, stdout, stderrdev/null/ בלתי מזיק כמו I/O deviceנפנה אותם ל –
כעת, לאחר כל הניתוקים, נוכל להריץ כל תוכנית•)(system ע"י קריאת מערכת daemonכ ”java –jar MyDaemon.jar"למשל –
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>
#define EXIT_SUCCESS 0#define EXIT_FAILURE 1
static void daemonize(void){ pid_t pid, sid; if ( getppid() == 1 ) return;
pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } if (pid > 0) { exit(EXIT_SUCCESS); } umask(0);
sid = setsid(); if (sid < 0) { exit(EXIT_FAILURE); }
if ((chdir("/")) < 0) { exit(EXIT_FAILURE); }
freopen( "/dev/null", "r", stdin); freopen( "/dev/null", "w", stdout); freopen( "/dev/null", "w", stderr);}
שתריץ עבורנו כלCנכתוב תוכנית ב daemon כ javaתוכנית
daemonizeנגדיר את הפונקציה כך שתבצע את הניתוקים ההכרחים
ותשאיר אותנו בתהליך הילד אחריהם.
ה מה זה אומר אםpid 1 שלנו שווה?
זה אומר שאנחנו...daemonכבר
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>
#define EXIT_SUCCESS 0#define EXIT_FAILURE 1
static void daemonize(void){ pid_t pid, sid; if ( getppid() == 1 ) return;
pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } if (pid > 0) { exit(EXIT_SUCCESS); } umask(0);
sid = setsid(); if (sid < 0) { exit(EXIT_FAILURE); }
if ((chdir("/")) < 0) { exit(EXIT_FAILURE); }
freopen( "/dev/null", "r", stdin); freopen( "/dev/null", "w", stdout); freopen( "/dev/null", "w", stderr);}
שתריץ עבורנו כלCנכתוב תוכנית ב daemon כ javaתוכנית
daemonizeנגדיר את הפונקציה כך שתבצע את הניתוקים ההכרחים
ותשאיר אותנו בתהליך הילד אחריהם.
יוצר העתק חדש של עושה?forkמה ה תהליך ההורה ומחזיר
process idתהליך הילד ימשיך
מאותה השורה בקוד.
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>
#define EXIT_SUCCESS 0#define EXIT_FAILURE 1
static void daemonize(void){ pid_t pid, sid; if ( getppid() == 1 ) return;
pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } if (pid > 0) { exit(EXIT_SUCCESS); } umask(0);
sid = setsid(); if (sid < 0) { exit(EXIT_FAILURE); }
if ((chdir("/")) < 0) { exit(EXIT_FAILURE); }
freopen( "/dev/null", "r", stdin); freopen( "/dev/null", "w", stdout); freopen( "/dev/null", "w", stderr);}
שתריץ עבורנו כלCנכתוב תוכנית ב daemon כ javaתוכנית
daemonizeנגדיר את הפונקציה כך שתבצע את הניתוקים ההכרחים
ותשאיר אותנו בתהליך הילד אחריהם.
?pid<0מהו pid>0?
מה קורה אם pid==0?
pid<0אומר שתהליך נכשל.forkה
pid>0אומר שאנו נמצאים בתהליך ההורה
ולכן נסיים אותו בהצלחה.pid=0אומר שאנו נמצאים
בתהליך הילד ולכן נמשיךעם הניתוקים שנותרו.
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>
#define EXIT_SUCCESS 0#define EXIT_FAILURE 1
static void daemonize(void){ pid_t pid, sid; if ( getppid() == 1 ) return;
pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } if (pid > 0) { exit(EXIT_SUCCESS); } umask(0);
sid = setsid(); if (sid < 0) { exit(EXIT_FAILURE); }
if ((chdir("/")) < 0) { exit(EXIT_FAILURE); }
freopen( "/dev/null", "r", stdin); freopen( "/dev/null", "w", stdout); freopen( "/dev/null", "w", stderr);}
שתריץ עבורנו כלCנכתוב תוכנית ב daemon כ javaתוכנית
daemonizeנגדיר את הפונקציה כך שתבצע את הניתוקים ההכרחים
ותשאיר אותנו בתהליך הילד אחריהם.
?umaskמה מגדיר
מגדיר את הרשאות התהליך(chmod )כמו הפקודה
)umask)027למשל chmod 750תקביל ל
(027)המשלים של
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>
#define EXIT_SUCCESS 0#define EXIT_FAILURE 1
static void daemonize(void){ pid_t pid, sid; if ( getppid() == 1 ) return;
pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } if (pid > 0) { exit(EXIT_SUCCESS); } umask(0);
sid = setsid(); if (sid < 0) { exit(EXIT_FAILURE); }
if ((chdir("/")) < 0) { exit(EXIT_FAILURE); }
freopen( "/dev/null", "r", stdin); freopen( "/dev/null", "w", stdout); freopen( "/dev/null", "w", stderr);}
שתריץ עבורנו כלCנכתוב תוכנית ב daemon כ javaתוכנית
daemonizeנגדיר את הפונקציה כך שתבצע את הניתוקים ההכרחים
ותשאיר אותנו בתהליך הילד אחריהם.
מה אנו רוצים לנתקכעת ?
signalsאת כל ערוצי ה שתהליך זה אולי ירשועשויים להפריע לו.
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>
#define EXIT_SUCCESS 0#define EXIT_FAILURE 1
static void daemonize(void){ pid_t pid, sid; if ( getppid() == 1 ) return;
pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } if (pid > 0) { exit(EXIT_SUCCESS); } umask(0);
sid = setsid(); if (sid < 0) { exit(EXIT_FAILURE); }
if ((chdir("/")) < 0) { exit(EXIT_FAILURE); }
freopen( "/dev/null", "r", stdin); freopen( "/dev/null", "w", stdout); freopen( "/dev/null", "w", stderr);}
שתריץ עבורנו כלCנכתוב תוכנית ב daemon כ javaתוכנית
daemonizeנגדיר את הפונקציה כך שתבצע את הניתוקים ההכרחים
ותשאיר אותנו בתהליך הילד אחריהם.
chdirמה הפקודה מבצעת?
.cdאת הפקודה directoryכדי להחליף ל
המתאים לשירות שלנו.
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>
#define EXIT_SUCCESS 0#define EXIT_FAILURE 1
static void daemonize(void){ pid_t pid, sid; if ( getppid() == 1 ) return;
pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } if (pid > 0) { exit(EXIT_SUCCESS); } umask(0);
sid = setsid(); if (sid < 0) { exit(EXIT_FAILURE); }
if ((chdir("/")) < 0) { exit(EXIT_FAILURE); }
freopen( "/dev/null", "r", stdin); freopen( "/dev/null", "w", stdout); freopen( "/dev/null", "w", stderr);}
שתריץ עבורנו כלCנכתוב תוכנית ב daemon כ javaתוכנית
daemonizeנגדיר את הפונקציה כך שתבצע את הניתוקים ההכרחים
ותשאיר אותנו בתהליך הילד אחריהם.
מה מתבצע כעתוכיצד?
descriptorsסגירה של ה הסטנדרטיים.
ודומיוstdin גם ה unixב מצביעים ל"קובץ".
בפקודות כאן אמרנו להםלהצביע מחדש ל"קובצי"
deviceאחרים – ל null
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
int main( int argc, char *argv[] ) { daemonize(); char command[80]="java"; int i; for(i=1;i<argc;i++){ strcat(command," "); strcat(command,argv[i]); } system(command); return 0;}
)(daemonize נוכל לקרוא ל mainכעת ב שאחריו נהיה למעשה בתהליך הילד שכעת
.daemonמנותק מהכל ומהווה למעשה
בדוגמא לקחנו את כל הארגומנטים וצירפנו .command תחת המחרוזת javaלפקודה
(java)יותר כללי היה לו לא היינו מקבעים את
.)(system ע"י shell נריץ ב commandאת
.Daemonלתוכנית המקומפלת נקרא ריצה למשל ע"י:
/. #Daemon –jar /home/eli/MyDaemon.jar
Daemonמה יקרה כשנריץ?ההורה
Init
Daemonהילד
java
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
int main( int argc, char *argv[] ) { daemonize(); char command[80]="java"; int i; for(i=1;i<argc;i++){ strcat(command," "); strcat(command,argv[i]); } system(command); return 0;}
)(daemonize נוכל לקרוא ל mainכעת ב שאחריו נהיה למעשה בתהליך הילד שכעת
.daemonמנותק מהכל ומהווה למעשה
בדוגמא לקחנו את כל הארגומנטים וצירפנו .command תחת המחרוזת javaלפקודה
(java)יותר כללי היה לו לא היינו מקבעים את
.)(system ע"י shell נריץ ב commandאת
.Daemonלתוכנית המקומפלת נקרא ריצה למשל ע"י:
/. #Daemon –jar /home/eli/MyDaemon.jar
?java ל killמה יקרה כשנעשה
Init
Daemonהילד
java
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
שימוש בכלים קיימיםכמו שראינו יכולנו להפוך את התוכנית שלנו •
לכלי גנרי להרצת כל תוכנית שאינה יכולה .daemonizeלעשות
כלי אחד כבר קיים תחת השם•start-stop-daemon
דוגמא לשימוש:•pidחשוב לייצר •
חדש ולשמור את תוכנו בקובץ כדי שהמע' לא , וכדי שמאוחר javaתטעה עם תהליך אחר של
השמור.pid ל stop--יותר נוכל לבצע
# sudo start-stop-daemon --start --quiet --background--make-pidfile --pidfile /var/run/eli.txt--startas java -- -jar /home/eli/MyDaemon.jar
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
בעיההריגת התהליך בצורה "ברוטאלית" שכזו, כפי שראינו •
בדוגמאות עד כה, לא מאפשרת לנו לבצע סגירות שלנו.javaאחרונות מתוך תוכנית ה
התהליך עצמו נסגר, ואין קריאה לאיזושהי מתודת •stop שמימשנו בתוך ה java.
אז מה ניתן לעשות כדי לסגור תוכנית כמו שצריך?•
כלשהו ולהאזין.port על socket ניתן למשל לפתוח • למשל, נבצע סגירה.”stop me“ כשתינתן הפקודה •”stop me“ הזה port נבנה תוכנית נוספת השולחת ל •
ופשוט נריץ אותה רגע לפני שנהרוג את התהליך בברוטאליות.
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
שימוש בכלים קיימיםאפשרות נוספת תהיה להשתמש בכלים •
. )הכלי המקובל ל apache של jsvcאחרים כגון java)
עם מתודות לאתחול, Daemonמספק ממשק •הפעלה, עצירה והריסה.
תפעיל את אותן המתודות ע"פ jsvcהפקודה •הפרמטרים שתקבל כשתופעל.
jsvc -cp /usr/share/java/commons-daemon.jar:/home/eli/MyService.jar Main #לדוגמא:•
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
שימוש בכלים קיימים
התקנה:http://commons.apache.org מתוך: sourceהורידו את ה •
/downloads/download_daemon.cgi
קמפלו את הקוד:•
packageכעת ניתן להעתיק את תיקיות ה • רגיל ואז java אל כל פרויקט javaשתחת
.Daemonלממש את הממשק
JAVA_HOME=/usr/bin/javaexport JAVA_HOMEcd daemon-1.0.1/src/native/unix./configuremake
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
שימוש בכלים קיימיםimport org.apache.commons.daemon.*;
public class Main implements Daemon{
@Overridepublic void destroy() {// TODO Auto-generated method stub}
@Overridepublic void init(DaemonContext context) throws Exception {// TODO Auto-generated method stub}
@Overridepublic void start() throws Exception {// TODO Auto-generated method stub
}
@Overridepublic void stop() throws Exception {// TODO Auto-generated method stub}
}
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
שימוש בכלים קיימים
עובד?jsvcאיך
יוצר
יוצרsignalsמפעיל ע"י
אתcontrolled processה
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
הפעלה בעת אתחול שבנינו יופעל עם daemonבד"כ נרצה שה •
אתחול המערכת. מכילה סקריפטים שטוענים etc/init.d/התיקייה •
daemons.בעת אתחול המערכת שלנו עם האתחול, daemonכדי להפעיל את ה •
נצטרך ליצור סקריפט הפעלה עבורו בתיקייה זו. אם כי אין זו חובה.bashסקריפט בד"כ נכתב ב •נראה כעת שתי דוגמאות של סקריפטים •
מוכנים.
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
הפעלה בעת אתחול•/etc/init.d/skeleton
.daemonsסקריפט שלדי עבור הרצת – שלנו.daemonניתן להעתיק ולהתאים ל –start-stop-daemonמשתמש ב –
•/etc/init.d/tomcat6.daemon כ tomcatסקריפט להרצת שרת ה –.jsvcמשתמש ב –
הקדמהDaemonכיצד נוצר
שימוש בכלים קיימיםהפעלה בעת אתחול
הטמעה
10 – תרגול 2 תכנות מתקדם 89-211
הטמעה ולא להריץ ישר forkמדוע היינו צריכים לעשות •
באותו התהליך?
מה הבעיה בשיטות שראינו בתחילת השיעור •וכיצד ניתן לפתור אותן?
?etc/init.d/למה משמשת התיקייה •
חישבו אילו התאמות תצטרכו לעשות בפרויקט • וגם Windowsהקורס כדי להריצו כשירות גם ב
.Linuxב