update-rc.d - نصب و پاک کردن init اسکریپت ها و لینک های آن (system V)

دستور update-rc.d برای پاک کردن، نصب کردن و آپدیت کردن لینک‌های اسکریپت‌های init  که بر پایه System V باشد مورد استفاده قرار می‌گیرد.

این دستور بیشتر در سیستم‌های دبیان‌بیس مورد استفاده و دستور chkconfig که کار مشابه‌ای رو انجام میده بیشتر در سیستم‌های redhat بیس مورد استفاده است.

رانلول چیست (سطح اجرا)؟

در سیستم‌های یونیکسی که آغازش سبک سیستم ۵ را پیاده‌سازی کرده‌اند، سطوح اجرا (runlevels) به مدهای عملیاتی سیستم عامل گفته می‌شود. به طور قراردادی ۷ سطح اجرا وجود دارد که از ٠ تا ٦ شماره‌گذاری شده‌اند؛ البته تا ده مد اجرا یعنی از 0 تا 9 می‌تواند تعریف و استفاده شود. یکی از این مدهای عملیاتی، مد تک‌کاربره است که می‌توان بجای عدد از نماد S استفاده کرد. تنها یک سطح اجرا هنگام بوت اجرا می‌شود و سطوح اجرا به ترتیب اجرا نمی‌شوند. به عنوان مثال هنگام بوت یکی از سطوح اجرای ٢ یا ٣ یا ۴ اجرا می‌شود نه اینکه اول ٢ سپس ٣ و بعد ۴.
 
«سطح اجرا» وضعیت دستگاه بعد از بوت شدن را تعریف می‌کند. سطوح اجرا معمولاً به وضعیت‌های زیر تخصیص یافته‌اند:
  • مد تک‌کاربره
  • مد چندکاربره بدون شروع سرویس‌های شبکه
  • مد چندکاربره با سرویس‌های شبکه
  • خاموش کردن سیستم
  • راه‌اندازی مجدد (ریبوت) سیستم

منبع

رانلول شماره ۶ برای ریستارت کردن سیستم و رانلول ۰ برای halt کردن سیستم مورد استفاده می‌شود. اطلاعات بیشتر در مورد halt به دستور shutdown مراجعه و قسمت «فرق بین halt و  power off» رو بخونین.

در لینوکس هر رانلول برای خودش یک دایرکتوری دارد که اسکریپت‌های داخل اون دایرکتوری‌ها یک سیمبلیک لینک به اسکریپت اصلی هستن. اسکریپت اصلی در آدرس etc/init.d/ ذخیزه می‌شود و لینک‌های اون داخل دایرکتوری‌های  etc/rcN.d/NNname/ ساخته می‌شود که عدد هر دایرکتوری نشان دهنده شماره رانلول هست:

etc/rc0.d
etc/rc1.d/
etc/rc2.d/
etc/rc3.d/
etc/rc4.d/
etc/rc5.d/
etc/rc6.d/

لینک‌های داخل این دایرکتوری‌ها  تعیین می‌کنن که داخل هر رانلول چه سرویس‌هایی باید اجرا شوند.

آدرس این فایل‌ها ممکنه در توزیعات مختلف متفاوت باشه ممکن هست که برای شما در یکی از ادرس های زیر باشن :

/etc/rc.d/rc?.d, /etc/init.d/rc?.d, /etc/rc?.d

نام‌گذاری لینک‌ها

اسم زیر رو در نظر بگیرین:

S20pidgin-ppa

s: یعنی start. به این معنی که این سرویس در این رانلول اجرا می‌شود اگر kباشه به معنی kill هست که این سرویس در این رانلول از کار می‌افتد. همیشه اول سرویس‌هایی که اول اسم‌شون kدارن فراخوانی می‌شن و بعد اون‌هایی که اول اسمشون sدارن فراحانی میشن.

20اولویت اجرا هستش. اگر سرویس B وابستگی به سرویسA  دارد پس باید اول سرویس A اجرا شود و بعد سرویس B اجرا شود. و برای از کار انداختن (kill) هم اول باید سرویس B ازکار بیفتد و بعد سرویس A. این اولویت رو از طریق عددی که در اول اسم لینک هست تعیین می‌کنیم. مثلا s20 قبل از s50 اجرا می شود و k50 از k20 زودتر  از کار میفته. به‌صورت استاندارد معمولا اگر برای start عدد 20 رو تعیین کردین برای stop عدد 100-20=80 رو باید تعیین کنین که میشه k80.

pidgin-ppa: اسم اسکریپت اصلی که در etc/init.d/ بودش.

نکته: وقتی اول اسم لینک‌مون sباشه دستوری که به اسکریپت اصلی فرستاده می‌شود (یعنی اسکریپتی که در init.d هست) به همراه آرگومان startفرستاده می‌شود. ولی وقتی که اولش kهست به همراه آرگومان stopفرستاده می‌شود. این دقیقا مثل همونی هست که خودمون به‌صورت دستی انجام می‌دیم. مثلا وقتی می‌خوایم سرویس bind9 رو از کار بندازیم دستور زیر رو می‌زنیم:

# service bind9 stop

یا دستور زیر

# /etc/init.d/bind9 stop

ساخت لینک

من در این‌جا یک فایل به اسم test رو با دستور زیر در etc/init.d/ قرار دادم تا در ادامه آموزش با اون کار کنیم:

aliabry@lp:/$ sudo touch /etc/init.d/test

ساده ترین شکل ساخت لینک استفاده از آپشن defaults هستش که خودش همه کارا رو انجام میده:

aliabry@lp:/$ sudo update-rc.d test defaults
update-rc.d: warning: /etc/init.d/test missing LSB information
update-rc.d: see <http://wiki.debian.org/LSBInitScripts>
 Adding system startup for /etc/init.d/test ...
   /etc/rc0.d/K20test -> ../init.d/test
   /etc/rc1.d/K20test -> ../init.d/test
   /etc/rc6.d/K20test -> ../init.d/test
   /etc/rc2.d/S20test -> ../init.d/test
   /etc/rc3.d/S20test -> ../init.d/test
   /etc/rc4.d/S20test -> ../init.d/test
   /etc/rc5.d/S20test -> ../init.d/test

این خطا رو (update-rc.d: warning: /etc/init.d/test missing LSB information)   نادیده بگیرین. به این خاطره که فایلمون خالی هستش.

همون‌طور که از خروجی معلوم هست:

در رانلول های ۰، ۱ و ۶ این اسکریپت رو برای از کار انداختن (stop) فراخوانی می‌کند و در رانلول های ۲، ۳، ۴ و ۵ برای راه اندازی (start) فراخوانی می‌کند و تمام اولویت‌ها رو هم عدد 20 داده. (تغییر عدد اولویت رو پایین‌تر گفتم)

پاک کردن لینک‌ها

برای پاک کردن لینک مورد نظرمون دستور رو به شکل زیر می‌زنیم:

aliabry@lp:/$ sudo update-rc.d -f test remove
 Removing any system startup links for /etc/init.d/test ...
   /etc/rc0.d/K20test
   /etc/rc1.d/K20test
   /etc/rc2.d/S20test
   /etc/rc3.d/S20test
   /etc/rc4.d/S20test
   /etc/rc5.d/S20test
   /etc/rc6.d/K20test

نکته: بدون آپشن f- هم می‌تونین دستور رو بزنین. ولی اگر اسکریپت اصلی در etc/init.d/ وجود داشته باشه (یعنی پاک نشده باشه) باید با آپشن f-دستور رو بزنین (مثل بالا) و گرنه ارور زیر رو می‌گیرین:

aliabry@lp:/$ sudo update-rc.d test remove
update-rc.d: /etc/init.d/test exists during rc.d purge (use -f to force)

ساخت لینک و تعیین اولویت

همون‌طور که در دستور اول دیدین خودش اولویت رو پیش‌فرض 20 می‌داد که اگر بخوایم اولویت رو تعیین کنیم دستور رو به شکل زیر بزنین عدد اول برای start و عدد دوم برای stop:

aliabry@lp:/$ sudo update-rc.d test defaults 25 75
update-rc.d: warning: /etc/init.d/test missing LSB information
update-rc.d: see <http://wiki.debian.org/LSBInitScripts>
 Adding system startup for /etc/init.d/test ...
   /etc/rc0.d/K75test -> ../init.d/test
   /etc/rc1.d/K75test -> ../init.d/test
   /etc/rc6.d/K75test -> ../init.d/test
   /etc/rc2.d/S25test -> ../init.d/test
   /etc/rc3.d/S25test -> ../init.d/test
   /etc/rc4.d/S25test -> ../init.d/test
   /etc/rc5.d/S25test -> ../init.d/test

در دستور بالا برای stop عدد 75 و برای start عدد 25 رو دادیم.

ساخت لینک و تعیین اولویت و رانلول

اگر بخوایم هر سه کار رو هم‌زمان انجام بدیم دستور رو به شکل زیر می‌زنیم:

نکته: نقطه‌هایی (.) که یکی قبل stop و یکی آخر دستور هست رو فراموش نکنین

aliabry@lp:/$ sudo update-rc.d test start 30 2 3 . stop 70 0 1 4 5 6 .
update-rc.d: warning: /etc/init.d/test missing LSB information
update-rc.d: see <http://wiki.debian.org/LSBInitScripts>
 Adding system startup for /etc/init.d/test ...
   /etc/rc0.d/K70test -> ../init.d/test
   /etc/rc1.d/K70test -> ../init.d/test
   /etc/rc4.d/K70test -> ../init.d/test
   /etc/rc5.d/K70test -> ../init.d/test
   /etc/rc6.d/K70test -> ../init.d/test
   /etc/rc2.d/S30test -> ../init.d/test
   /etc/rc3.d/S30test -> ../init.d/test

در دستور بالا تعیین کردیم که:

اولویت start عدد 30 باشد و عمل start رو در رانلول‌های ۲ و ۳ انجام میده.

اولویت stop عدد 70 باشد و عمل stop رو در رانلول های ۰، ۱، ۴، ۵ و ۶ انجام میده.

به این شکل هم می‌تونیم دستور رو بزنیم که فقط لینک‌های استارت رو بسازه (برای stop هم به همین شکل هست):

aliabry@lp:/$ sudo update-rc.d test start 30 2 3 .
update-rc.d: warning: /etc/init.d/test missing LSB information
update-rc.d: see <http://wiki.debian.org/LSBInitScripts>
 Adding system startup for /etc/init.d/test ...
   /etc/rc2.d/S30test -> ../init.d/test
   /etc/rc3.d/S30test -> ../init.d/test

آپدیت کردن لینک‌ها

اگر لینک‌هامون هم‌اکنون وجود دارن و می‌خوایم که تغییرات روشون ایجاد کنیم بدون این‌که اول پاکشون کنیم و بعد بسازیم‌شون دستور رو به‌صورت زیر می‌تونیم بزنیم خودش همه کارهای لازم رو انجام میده.

برای start از enableو برای stop از disableاستفاده می‌کنیم.

نکته: در آپدیت کردن برای رانلول فقط رانلول‌های ۲، ۳، ۴، ۵ و S رو می‌شه تعیین کرد (S همون رانلول 1 هست).

در زیر می‌گیم که فایل test در رانلول‌های ۲، ۳، ۴ و ۵ رو به حالت stop تغییر بده.

این دستور اول میاد لینک‌ها رو پاک می‌کنه و با توجه به ورودی که دادیم لینک‌ها رو آپدیت می‌کند که لینک‌های رانلول ۲، ۳، ۴ و ۵ که به‌صورت start بودن رو به‌صورت stop در میاره.

aliabry@lp:/$ sudo update-rc.d test disable  2 3 4 5
update-rc.d: warning: /etc/init.d/test missing LSB information
update-rc.d: see <http://wiki.debian.org/LSBInitScripts>
 Disabling system startup links for /etc/init.d/test ...
 Removing any system startup links for /etc/init.d/test ...
   /etc/rc0.d/K75test
   /etc/rc1.d/K75test
   /etc/rc2.d/S25test
   /etc/rc3.d/S25test
   /etc/rc4.d/S25test
   /etc/rc5.d/S25test
   /etc/rc6.d/K75test
 Adding system startup for /etc/init.d/test ...
   /etc/rc0.d/K75test -> ../init.d/test
   /etc/rc1.d/K75test -> ../init.d/test
   /etc/rc6.d/K75test -> ../init.d/test
   /etc/rc2.d/K75test -> ../init.d/test
   /etc/rc3.d/K75test -> ../init.d/test
   /etc/rc4.d/K75test -> ../init.d/test
   /etc/rc5.d/K75test -> ../init.d/test


multiuser (مخصوص ubuntu)

multiuser مخصوص ubuntu هستش که در رانلول‌های ۲، ۳، ۴ و ۵ عمل start و در ۱ عمل stop رو انجام میده که در نسخه‌های جدیدتر ubuntu دیگه نیستش اطلاعات بیشتر در مورد multiuser به این لینک مراجعه کنید.

# update-rc.d foobar multiuser

معادل دستور بالا دقیقا میشه دستور زیر:

# update-rc.d foobar start 20 2 3 4 5 . stop 20 1 .

در صفحه man دستور update-rc.d هم چندین تا مثال داره که مثال‌های خوبی هستن:

http://manpages.ubuntu.com/manpages/raring/man8/update-rc.d.8.html