الفرق بين المراجعتين ل"Ruby/Kernel/spawn"

من موسوعة حسوب
< Ruby‏ | Kernel
اذهب إلى التنقل اذهب إلى البحث
(أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE: التابع <code>spawn‎</code> الخاص بالصنف <code>Kernel</code> في روبي}}</noinclude> تصنيف: Ruby تصني...')
 
ط
 
(8 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة)
سطر 3: سطر 3:
 
[[تصنيف: Ruby Method]]
 
[[تصنيف: Ruby Method]]
 
[[تصنيف: Ruby Kernel]]
 
[[تصنيف: Ruby Kernel]]
ينفذ التابع spawn تعليمة محددة، ثم يعيد معرفها (pid).
+
ينفذ التابع <code>spawn</code> تعليمة محددة، ثم يعيد معرفها (pid).
 
+
==البنية العامة==
يشبه هذا التابع <code>#system</code>ـ غير أنّه لا ينتظر إلى أن ينتهي تنفيذ الأمر.
+
<syntaxhighlight lang="ruby">spawn([env,] command... [,options])  → pid
يجب على العملية الأم (parent process) أن تستخدم <code>Process.wait</code> لتحصيل حالة الإنهاء للعملية الفرعية، أو تستخدم <code>Process.detach</code> لتسجيل عدم الاهتمام بحالتها؛ خلاف ذلك، قد يُراكم نظام التشغيل عمليات ميتة (zombie processes).
+
spawn([env,] command... [,options])  → pid‎</syntaxhighlight>يشبه التابعُ <code>spawn</code> التابعَ <code>[[Ruby/Kernel/system|system]]</code> باستثناء أنّه لا ينتظر إلى أن ينتهي تنفيذ الأمر.
التابع spawn لديه مجموعة من الخيارات لتحديد خصائص العملية:
 
<syntaxhighlight lang="ruby">env: hash
 
  name => val : set the environment variable
 
  name => nil : unset the environment variable
 
  the keys and the values except for +nil+ must be strings.
 
command...:
 
  commandline                : command line string which is passed to the standard shell
 
  cmdname, arg1, ...          : command name and one or more arguments (This form does not use the shell. See below for caveats.)
 
  [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
 
options: hash
 
  clearing environment variables:
 
    :unsetenv_others => true  : clear environment variables except specified by env
 
    :unsetenv_others => false : don't clear (default)
 
  process group:
 
    :pgroup => true or 0 : make a new process group
 
    :pgroup => pgid      : join the specified process group
 
    :pgroup => nil      : don't change the process group (default)
 
  create new process group: Windows only
 
    :new_pgroup => true  : the new process is the root process of a new process group
 
    :new_pgroup => false : don't create a new process group (default)
 
  resource limit: resourcename is core, cpu, data, etc.  See Process.setrlimit.
 
    :rlimit_resourcename => limit
 
    :rlimit_resourcename => [cur_limit, max_limit]
 
  umask:
 
    :umask => int
 
  redirection:
 
    key:
 
      FD              : single file descriptor in child process
 
      [FD, FD, ...]  : multiple file descriptor in child process
 
    value:
 
      FD                        : redirect to the file descriptor in parent process
 
      string                    : redirect to file with open(string, "r" or "w")
 
      [string]                  : redirect to file with open(string, File::RDONLY)
 
      [string, open_mode]       : redirect to file with open(string, open_mode, 0644)
 
      [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
 
      [:child, FD]              : redirect to the redirected file descriptor
 
      :close                    : close the file descriptor in child process
 
    FD is one of follows
 
      :in    : the file descriptor 0 which is the standard input
 
      :out    : the file descriptor 1 which is the standard output
 
      :err    : the file descriptor 2 which is the standard error
 
      integer : the file descriptor of specified the integer
 
      io      : the file descriptor specified as io.fileno
 
  file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
 
    :close_others => true : don't inherit
 
  current directory:
 
    :chdir => str
 
  The 'cmdname, arg1, ...' form does not use the shell. However,
 
  on different OSes, different things are provided as built-in
 
  commands. An example of this is 'echo', which is a built-in
 
  on Windows, but is a normal program on Linux and Mac OS X.
 
  This means that `Process.spawn 'echo', '%Path%'` will display
 
  the contents of the `%Path%` environment variable on Windows,
 
  but `Process.spawn 'echo', '$PATH'` prints the literal '$PATH'.‎</syntaxhighlight>
 
إن كانت القيمة أالمعطاة للوسيط XXXX قاموسًا (hash)، فسيتم تحديث البيئة بواسطة <code>env</code> قبل <code>env</code> في العملية الفرعية. إن كان لأحد مدخلات <code>exec(2)</code> القيمة nil، فسيُحذف ذلك المتغير.
 
 
 
إن كانت القيمة أالمعطاة للوسيط <code>env</code> قاموسًا، فسيحدد مجموعة العمليات (process group)، وينشئ مجموعة عمليات جديدة، ويحدد الموارد، والمجلد الحالي، وتقنيع (umask) وإعادة التوجيه العملية الفرعية. يمكن أيضًا تحديدها لمحو متغيرات البيئة.
 
المفتاح <code>options</code> في <code>:unsetenv_others</code> يؤدي إلى محو متغيرات البيئة فضلًا عن تلك المحددة بواسطة <code>options</code>.
 
  
يحدد المفتاح <code>env</code> في <code>:pgroup</code> مجموعة العملية. يجب أن تساوي القيمة المقابلة true، أو صفر، أو عددًا صحيحًا موجبًا، أو nil. القيمتان true وصفر تجعلان العملية عمليةً قائدة (process leader) لمجموعة عمليات جديدة. عدد صحيح موجب غير معدوم يجعل العملية تنضم إلى مجموعة العمليات المعطاة. أما القيمة الافتراضية nil، فتُبقي العملية في نفس مجموعة العمليات.
+
يجب على العملية الأب (parent process) أن تستخدم التابع <code>[[Ruby/Process/wait|Process.wait]]</code> لتحصيل حالة الإنهاء للعملية الفرعية، أو تستخدم <code>[[Ruby/Process/detach|Process.detach]]</code> لتسجيل عدم الاهتمام بحالتها؛ خلاف ذلك، قد يُراكم نظام التشغيل عمليات ميتة (zombie processes).
  
المفتاح <code>options</code> في <code>:new_pgroup</code> يؤدي إلى تمرير الراية <code>options</code> إلى <code>CREATE_NEW_PROCESS_GROUP</code>، والتي هي واجهة برمجية لنظام ويندوز (Windows API). هذا الخيار متاح فقط لنظام التشغيل ويندوز. القيمة true تعني أن العملية الجديدة ستكون العملية الجذرية لمجموعة العمليات الجديدة. يتم تعطيل CTRL + C في العملية الجديدة. هذه الراية ضرورية لـ <code>CreateProcessW()</code> في العملية الفرعية. قيمة :new_pgroup تساوي false افتراضيًا.
+
التابع <code>spawn</code> لديه مجموعة من الخيارات لتحديد خاصيات العملية:
 +
{| class="wikitable"
 +
! colspan="2" |env: hash
 +
|-
 +
|<code>name => val</code>
 +
|يضبط متغيرات البيئة.
 +
|-
 +
|<code>name => nil</code>
 +
|يلغي ضبط متغيرات البيئة.
 +
|-
 +
| colspan="2" |ينبغي تكون المفاتيح والقيم سلاسل نصية باستثناء <code>nil</code>.
 +
|-
 +
! colspan="2" |...command
 +
|-
 +
|<code>commandline</code>
 +
|تعليمة نصية تُمرر إلى الصدفة القياسية.
 +
|-
 +
|<code>... ,cmdname, arg1</code>
 +
|تعليمة وواحد أو أكثر من الوسائط (هذا الشكل لا يستخدم الصدفة).
 +
|-
 +
|<code>‎[cmdname, argv0], arg1, ...‎</code>
 +
|تعليمة والوسيط <code>argv[0]‎</code> ووسيط واحد أو أكثر.
 +
|-
 +
! colspan="2" |ptions: hash
 +
|-
 +
| colspan="2" |مسح متغيرات البيئة (clearing environment variables)
 +
|-
 +
|<code>unsetenv_others => true:</code>
 +
|مسح متغيرات البيئة باستثناء المحددة من قبل <code>env</code>.
 +
|-
 +
|<code>unsetenv_others => false:</code>
 +
|عدم مسح المتغيرات - الخيار الافتراضي.
 +
|-
 +
| colspan="2" |process group: (مجموعة العمليات)
 +
|-
 +
|<code>pgroup => true or 0:</code>
 +
|إنشاء مجموعة عمليات جديدة.
 +
|-
 +
|<code>pgroup => pgid:</code>
 +
|الانضمام إلى مجموعة العمليات المحددة.
 +
|-
 +
|<code>pgroup => nil:</code>
 +
|عدم تغيير مجموعة العمليات (الافتراضي).
 +
|-
 +
| colspan="2" |إنشاء مجموعة عمليات جديدة: ويندوز فقط
 +
|-
 +
|<code>new_pgroup => true:</code>
 +
|العملية الجديدة هي العملية الأصل لمجموعة عمليات جديدة.
 +
|-
 +
|<code>new_pgroup => false:</code>
 +
|عدم إنشاء مجموعة عمليات جديدة (الافتراضي).
 +
|-
 +
| colspan="2" |اسم المورد (resourcename): هو نواة (core)، معالج (cpu)، بيانات، ...إلخ. انظر التابع <code>[[Ruby/Process/setrlimit|Process.setrlimit]]</code>.
 +
|-
 +
|<code>‎:rlimit_resourcename => limit</code>
 +
|
 +
|-
 +
|<code>‎:rlimit_resourcename => [cur_limit, max_limit]‎</code>
 +
|
 +
|-
 +
| colspan="2" |umask:
 +
|-
 +
|<code>umask => int:</code>
 +
|
 +
|-
 +
| colspan="2" |إعادة التوجيه (redirection):
 +
* المفتاح (key):
 +
|-
 +
|<code>FD</code>
 +
|واصف ملف واحد في العملية الفرعية.
 +
|-
 +
|<code>[FD, FD, ...‎]</code>
 +
|واصفات ملف متعددة في العملية الفرعية.
 +
|-
 +
| colspan="2" |
 +
* القيمة (value):
 +
|-
 +
|<code>FD</code>
 +
|يعيد التوجيه إلى واصف الملف في العملية الأب.
 +
|-
 +
|<code>string</code>
 +
|يعيد التوجيه إلى الملف مع <code>open(string, "r" or "w"‎)‎</code>.
 +
|-
 +
|<code>[string]</code>
 +
|يعيد التوجيه إلى الملف مع <code>open(string, File::RDONLY)‎</code>.
 +
|-
 +
|<code>[string, open_mode]</code>
 +
|يعيد التوجيه إلى الملف مع <code>open(string, open_mode, 0644)‎</code>.
 +
|-
 +
|<code>[string, open_mode, perm]</code>
 +
|يعيد التوجيه إلى الملف مع <code>open(string, open_mode, perm)‎</code>.
 +
|-
 +
|<code>[child, FD:]</code>
 +
|يعيد التوجيه إلى واصف الملف المعاد توجيهه.
 +
|-
 +
|<code>close:</code>
 +
|يغلق واصف الملف في العملية الفرعية.
 +
|-
 +
| colspan="2" |واصف الملف FD هو أحد القيم التالية:
 +
|-
 +
|<code>in:</code>
 +
|واصف الملف رقم 0 والذي هو الدخل القياسي.
 +
|-
 +
|<code>out:</code>
 +
|واصف الملف رقم 1 والذي هو الخرج القياسي.
 +
|-
 +
|<code>err:</code>
 +
|واصف الملف رقم 2 والذي هو مجرى الخطأ القياسي.
 +
|-
 +
|<code>integer</code>
 +
|واصف الملف ذو العدد الصحيح المحدد.
 +
|-
 +
|<code>io</code>
 +
|واصف الملف <code>[[Ruby/IO/fileno|io.fileno]]</code>.
 +
|-
 +
| colspan="2" |وراثة واصف الملف: أغلق واصفات الملفات غير الموجَّهة وغير القياسية (مثل 3، و 4، و 5، ...إلخ.) أو لا.
 +
|-
 +
|<code>close_others => true:</code>
 +
|لا تستعمل الواصفات الموروثة.
 +
|-
 +
| colspan="2" |المجلد الحالي:
 +
|-
 +
|<code>chdir => str:</code>
 +
|
 +
|-
 +
| colspan="2" | لا يستخدم الشكل '<code>cmdname, arg1, ...‎</code>' الصدفة. لكن في بعض أنظمة التشغيل، يتم توفير أوامر مدمجة (built-in) مثل "<code>echo</code>"، المُدمج في ويندوز ، خلافًا للأنظمة لينكس وماك التي يعد فيها أمرًا طبيعيًّا. وهذا يعني أن  <code>`Process.spawn 'echo', '%Path%'‎`</code> سيعرض محتويات متغير البيئة `<code>%Path%</code>` على ويندوز، لكن <code>`Process.spawn 'echo', '$PATH'‎`</code> سيطبع '‎<code>$PATH‎</code>' حرفيًّا.
 +
|}
 +
إن كانت القيمة المعطاة للمعامل <code>env</code> [[Ruby/Hash|جدولًا من النوع Hash]]، فسيتم تحديث البيئة بواسطة <code>env</code> قبل تنفيذ <code>exec(2)‎</code> في العملية الفرعية. إن كان لأحد مدخلات المعامل <code>env</code> القيمة <code>nil</code>، فسيُحذَف ذلك المتغير.<syntaxhighlight lang="ruby"># set FOO as BAR and unset BAZ.
 +
pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)</syntaxhighlight>إن كانت القيمة المعطاة للمعامل <code>options</code> [[Ruby/Hash|جدولًا من النوع Hash]]، فسيُحدِّد مجموعة العمليات (process group)، وينشئ مجموعة عمليات جديدة، ويحدد الموارد، والمجلد الحالي، ويقوم بتقنيع (umask) وإعادة توجيه العملية الفرعية. ويمكن أيضًا ضبطها لمحو متغيرات البيئة.
  
يحدد المفتاح <code>Process.kill(:SIGINT,
+
المفتاح ‎<code>:unsetenv_others</code> في <code>options</code> يؤدي إلى محو متغيرات البيئة فضلًا عن تلك المحددة بواسطة <code>env</code>.<syntaxhighlight lang="ruby">pid = spawn(command, :unsetenv_others=>true) # no environment variable
pid)</code>foo حدود الموارد. يجب أن تكون foo إحدى أنواع الموارد مثل <code>:rlimit_</code>. ويجب أن تكون القيمة المقابلة إما عددًا صحيحًا، أو مصفوفة تحتوي على عدد أوعددين صحيحين: مثل الوسيطين cur_limit و max_limit في <code>core</code>.
+
pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only
 +
</syntaxhighlight>يحدد المفتاح ‎<code>:pgroup</code> في الخيارات <code>options</code> مجموعة العملية. يجب أن تساوي القيمة المقابلة <code>true</code>، أو صفرًا، أو عددًا صحيحًا موجبًا، أو القيمة <code>nil</code>. القيمتان <code>true</code> والصفر 0 تجعلان العملية عمليةً قائدةً (process leader) لمجموعة عمليات جديدة. عدد صحيح موجب غير معدوم سيجعل العملية تنضم إلى مجموعة العمليات المعطاة. أما القيمة الافتراضية <code>nil</code>، فستُبقي العملية في نفس مجموعة العمليات.<syntaxhighlight lang="ruby">pid = spawn(command, :pgroup=>true) # process leader
 +
pid = spawn(command, :pgroup=>10) # belongs to the process group 10
 +
</syntaxhighlight>المفتاح ‎<code>:new_pgroup</code> في الخيارات <code>options</code> يؤدي إلى تمرير الراية <code>CREATE_NEW_PROCESS_GROUP</code> إلى <code>CreateProcessW()‎</code>، والتي هي واجهة برمجية في أنظمة ويندوز (Windows API). هذا الخيار متاح فقط لنظام التشغيل ويندوز. القيمة <code>true</code> تعني أن العملية الجديدة ستكون العملية الأب لمجموعة العمليات الجديدة. يتم تعطيل <code>CTRL + C</code> في العملية الجديدة. هذه الراية ضرورية للتابع <code>[[Ruby/Process/kill|Process.kill(:SIGINT,pid)‎]]</code> في العملية الفرعية.
  
يحدد المفتاح <code>Process.setrlimit</code> في <code>:umask</code> التقنيع (umask).
+
قيمة <code>new_pgroup:</code> تساوي <code>false</code> افتراضيًا.<syntaxhighlight lang="ruby">pid = spawn(command, :new_pgroup=>true)  # new process group
 +
pid = spawn(command, :new_pgroup=>false) # same process group
 +
</syntaxhighlight>يحدِّد المفتاح ‎<code>:rlimit_foo</code> [[Ruby/Process/setrlimit|حدود الموارد]]. ويجب أن تكون <code>foo</code> إحدى أنواع الموارد مثل <code>core</code>. كما يجب أن تكون القيمة المقابلة إما عددًا صحيحًا، أو مصفوفةً تحتوي على عدد أوعددين صحيحين مثل الوسيطين <code>cur_limit</code> و <code>max_limit</code> في <code>[[Ruby/Process/setrlimit|Process.setrlimit]]</code>.<syntaxhighlight lang="ruby">cur, max = Process.getrlimit(:CORE)
 +
pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary.
 +
pid = spawn(command, :rlimit_core=>max) # enable core dump
 +
pid = spawn(command, :rlimit_core=>0) # never dump core.
 +
</syntaxhighlight>يحدد المفتاح ‎<code>:umask</code> في الخيارات <code>options</code> التقنيع (umask).<syntaxhighlight lang="ruby">pid = spawn(command, :umask=>077)
  
تحدد المفاتيح: :in, و :out و :err و، عدد من integer، وكائن <code>options</code> و مصفوفة إعادة توجيه. إعادة التوجيه تحدد واصف ملف (file descriptor) في العملية التابعة.
+
</syntaxhighlight>يحدِّد المفتاح ‎<code>:in</code> و <code>out:</code> و <code>err:</code> و <code>[[Ruby/Integer|integer]]</code> و <code>[[Ruby/IO|io]]</code> و<nowiki/>[[Ruby/Array|المصفوفة]] إعادة توجيه.
على سبيل المثال، يمكن دمج stderr في stdout كما يلي:
 
  
تحدد مفاتيح القاموس واصف ملف في العملية الفرعية التي بدأها <code>IO</code>. أما err، 2 و STDERR فيعيّنان مجرى الخطأ القياسي (stderr).
+
تحدد إعادة التوجيه واصف ملف (file descriptor) في العملية الابن. على سبيل المثال، يمكن دمج <code>stderr</code> في <code>stdout</code> كما يلي:<syntaxhighlight lang="ruby">pid = spawn(command, :err=>:out)
تعيّن قيم القاموس واصف ملف في العملية الأم، والتي تستدعي <code>spawn</code>. : out، فيما يحدد :out, 1 و STDOUT ي مجرى الإخراج القياسي (stdout).
+
pid = spawn(command, 2=>1)
في المثال أعلاه، لم يُحدّد مجرى الإخراج القياسي في العملية الفرعية. لذلك فهو يرثها من العملية الأم.
+
pid = spawn(command, STDERR=>:out)
يمكن تحديد مجرى الإدخال القياسي (stdin) بواسطة: :in, 0 و STDIN.
+
pid = spawn(command, STDERR=>STDOUT)
يمكن تحديد اسم ملف كقيمة في قاموس.
+
</syntaxhighlight>تحدد مفاتيح [[Ruby/Hash|الجدول Hash]] واصف الملف في العملية الفرعية التي بدأها <code>spawn</code>. أما <code>err:</code>، و <code>2</code>، و <code>STDERR</code> فيعيّنان مجرى الخطأ القياسي (stderr).
  
بالنسبة إلى stdout و stderr (أو توليفة منهما) ، يتم فتحهما في وضع الكتابة. وإلا فسيُعتمد وضع القراءة خلاف ذلك.
+
تعيّن قيم [[Ruby/Hash|الجدول Hash]] واصف ملف في العملية الأب، والتي تستدعي <code>spawn</code>. أما  <code>out:</code> و <code>1</code> و <code>STDOUT</code> فتحدد مجرى الخرج القياسي (stdout).
لتحديد رايات وأذونات إنشاء الملفات بشكل صريح، يتم استخدام مصفوفة بدلاً من ذلك.
 
  
تحدد المصفوفة اسم الملف والرايات والأذونات. الرايات قد تكون سلاسل نصية أو أعدادًا صحيحة. إذا حُذفت الرايات أو أعطيت القيمة nil، فستُفترض File :: RDONLY. يجب أن يكون الإذن عددًا صحيحًا. إذا تم حذف الإذن أو كان يساوي nil، يتم افتراض القيمة 0644.
+
في المثال أعلاه، لم يُحدّد مجرى الخرج القياسي في العملية الفرعية. لذلك فهو يرثها من العملية الأب.
إذا تم تحديد مصفوفة من كائنات IOs ومن الأعداد الصحيحة كمفتاح للقاموس، سيتم إعادة توجيه جميع العناصر.
 
  
هناك طريقة أخرى لدمج عدة واصفات ملفات وهي [: child، fd]. والتي تعني واصف الملف في العملية الفرعية. وهو مختلف عن fd. على سبيل المثال،: err =>: out تعني إعادة توجيه المجرى stderr الفرعي إلى المجرى stdout الأم. ولكن: err => [: child،: out] تعني إعادة توجيه المجرى stderr الفرعي إلى المجرى stdout الفرعي. سيكونان مختلفان إذا أُعيد توجيه المجرىلففا stdout في العملية الفرعية على النحو التالي.
+
يمكن تحديد مجرى الدخل القياسي (stdin) بواسطة <code>in:</code> و <code>0</code> و <code>STDIN</code>.
  
يمكن استخدام [: child،: out] لدمج المجرى stderr في المجرى stdout في <code>spawn</code>. في هذه الحالةا، يعيد <code>IO.popen</code> توجيه المجرى stdout إلى أنبوب (pipe) في العملية الفرعية، حيث تشير [: child ،: out] إلى المجرى stdout المعاد توجيهه.
+
يمكن تحديد اسم ملف كقيمة في [[Ruby/Hash|الجدول Hash]].<syntaxhighlight lang="ruby">pid = spawn(command, :in=>"/dev/null") # read mode
 +
pid = spawn(command, :out=>"/dev/null") # write mode
 +
pid = spawn(command, :err=>"log") # write mode
 +
pid = spawn(command, [:out, :err]=>"/dev/null") # write mode
 +
pid = spawn(command, 3=>"/dev/null") # read mode
 +
</syntaxhighlight>بالنسبة إلى <code>stdout</code> و <code>stderr</code> (أو مزيج منهما) ، يتم فتحهما في وضع الكتابة. وإلا فسيُعتمد وضع القراءة.
  
يحدد المفتاح <code>IO.popen</code> في <code>:chdir</code> المجلد الحالي.
+
لتحديد رايات وأذونات إنشاء الملفات بشكل صريح، يمكن استخدام مصفوفة.<syntaxhighlight lang="ruby">pid = spawn(command, :in=>["file"]) # read mode is assumed
 +
pid = spawn(command, :in=>["file", "r"])
 +
pid = spawn(command, :out=>["log", "w"]) # 0644 assumed
 +
pid = spawn(command, :out=>["log", "w", 0600])
 +
pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])
  
تغلق spawn افتراضيا جميع الواصفات غير المحددة وغير القياسية. الواصفات "القياسية" هي 0 و 1 و 2. يتم تحديد هذا السلوك بواسطة الخيار: close_others. الخيار: close_others لا يؤثر على الواصفات القياسية، التي يتم إغلاقها فقط في حالة تم تحديد :close بشكل صريح.
+
</syntaxhighlight>تحدد المصفوفة اسم الملف والرايات والأذونات. الرايات قد تكون سلاسل نصية أو أعدادًا صحيحةً. إذا حُذفَت الرايات أو كانت قيمتها <code>nil</code>، فستُستعمَل القيمة <code>File::RDONLY</code> الافتراضية. يجب أن يكون الإذن عددًا صحيحًا. إذا تم حذف الإذن أو كان يساوي <code>nil</code>، فسيتم اعتماد القيمة <code>0644</code> الافتراضية.
  
قيمة: close_others تساوي true بشكل افتراضي بالنسبة للتابع spawn و <code>options</code>.
+
إذا تم تحديد مصفوفة من كائنات <code>[[Ruby/IO|IO]]</code> ومن الأعداد الصحيحة كمفتاح [[Ruby/Hash|للجدول Hash]]، فسيتم إعادة توجيه جميع العناصر.<syntaxhighlight lang="ruby"># stdout and stderr is redirected to log file.
لاحظ أنه العناصر fds التي تم تعيين الراية خاصتها close-on-exec ستُغلق بغض النظر عن الخيار close_others.
+
# The file "log" is opened just once.
لذلك يمكن استخدام <code>IO.popen</code> و spawn كـ <code>IO.pipe</code>.
+
pid = spawn(command, [:out, :err]=>["log", "w"])
 +
</syntaxhighlight>هناك طريقة أخرى لدمج عدة واصفات ملفات وهي <code>[‎:child، fd]</code>. والتي تعني واصف الملف في العملية الفرعية. وهو مختلف عن <code>fd</code>. على سبيل المثال، تعني <code>err =>:out</code> إعادة توجيه المجرى <code>stderr</code> للعملية الفرعية إلى المجرى <code>stdout</code> للعملية الأب. ولكن ‎<code>:err => [:child،:out]‎</code> تعني إعادة توجيه المجرى <code>stderr</code> للعملية الفرعية إلى المجرى <code>stdout</code> للعملية الفرعية نفسها، إذ سيكونان مختلفين إذا أُعيد توجيه المجرى <code>stdout</code> في العملية الفرعية على النحو التالي.<syntaxhighlight lang="ruby"># stdout and stderr is redirected to log file.
 +
# The file "log" is opened just once.
 +
pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out])
 +
</syntaxhighlight>يمكن استخدام <code><nowiki>[‎:child، :out]</nowiki></code> لدمج المجرى <code>stderr</code> في المجرى <code>stdout</code> في <code>[[Ruby/IO/popen|IO.popen]]</code>. في هذه الحالة، يعيد [[Ruby/IO/popen|<code>IO.popen</code>]] توجيه المجرى <code>stdout</code> إلى أنبوب (pipe) في العملية الفرعية، إذ تشير <code><nowiki>[‎:child ، :out]</nowiki></code> إلى المجرى <code>stdout</code> المعاد توجيهه.<syntaxhighlight lang="ruby">io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]])
 +
p io.read #=> "out\nerr\n"
 +
</syntaxhighlight>يحدد المفتاح ‎<code>:chdir</code> في <code>options</code> المجلد الحالي.<syntaxhighlight lang="ruby">pid = spawn(command, :chdir=>"/var/tmp")
  
يتم تحديد :close كقيمة قاموس لإغلاق عنصر fd بشكل فردي.
+
</syntaxhighlight>تغلق <code>spawn</code> افتراضيًّا جميع الواصفات غير المحددة وغير القياسية. الواصفات "القياسية" هي <code>0</code> و <code>1</code> و <code>2</code>. يتم تحديد هذا السلوك بواسطة الخيار: <code>‎:close_others</code>. الخيار ‎<code>:close_others</code> لا يؤثر على الواصفات القياسية التي يتم إغلاقها إلا في حالة تم تحديد <code>:close</code> بشكل صريح.<syntaxhighlight lang="ruby">pid = spawn(command, :close_others=>true)  # close 3,4,5,... (default)
 +
pid = spawn(command, :close_others=>false) # don't close 3,4,5,...
 +
</syntaxhighlight>قيمة <code>‎:close_others</code> تساوي <code>true</code> بشكل افتراضي، بالنسبة للتابع <code>spawn</code> و [[Ruby/IO/popen|<code>IO.popen</code>]].
  
إذا كانت هناك حاجة إلى توريث واصف الملف، فيمكن استخدام io => io.
+
لاحظ أن واصفات الملفات التي تم تعيين الراية <code>close-on-exec</code> لها ستُغلق بغض النظر عن الخيار <code>close_others</code>. لذلك يمكن استخدام التابع <code>[[Ruby/IO/pipe|IO.pipe]]</code> والتابع <code>spawn</code> مثل التابع [[Ruby/IO/popen|<code>IO.popen</code>]].<syntaxhighlight lang="ruby"># similar to r = IO.popen(command)
 +
r, w = IO.pipe
 +
pid = spawn(command, :out=>w)  # r, w is closed in the child process.
 +
w.close
 +
</syntaxhighlight>يتم تحديد <code>close:</code> كقيمة في [[Ruby/Hash|الجدول Hash]] لإغلاق واصف ملف بشكل فردي.<syntaxhighlight lang="ruby">f = open(foo)
 +
system(command, f=>:close)        # don't inherit f.
 +
</syntaxhighlight>إذا كانت هناك حاجة إلى توريث واصف الملف، فيمكن استخدام <code>io => io</code>.<syntaxhighlight lang="ruby"># valgrind has --log-fd option for log destination.
 +
# log_w=>log_w indicates log_w.fileno inherits to child process.
 +
log_r, log_w = IO.pipe
 +
pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w)
 +
log_w.close
 +
p log_r.read
 +
</syntaxhighlight>من الممكن أيضًا تبادل واصفات الملفات.<syntaxhighlight lang="ruby">pid = spawn(command, :out=>:err, :err=>:out)
  
من الممكن أيضًا تبادل واصفات الملفات.
+
</syntaxhighlight>تحدد مفاتيح [[Ruby/Hash|الجدول Hash]] واصفات الملفات في العملية الفرعية بينما تحدد قيم [[Ruby/Hash|الجدول Hash]] واصفات الملفات في العملية الأب. بناءً على ذلك، يحدد المثال أعلاه تبادل المَجرّيين <code>stdout</code> و <code>stderr</code>. داخليًا، يستخدم <code>spawn</code> واصف ملف إضافي لحل هذا التعيين الدوري لواصفات الملفات.
  
تحدد مفاتيح القاموس واصفات الملفات في العملية الفرعية. فيما تحدد قيم القاموس واصفات الملفات في العملية الأم. بهذا يحدد المثال أعلاه تبادل المجريين stdout و stderr. داخليًا، يستخدم <code>IO.popen</code> واصف ملف إضافي لحل هذا التعيين الدوري لواصفات الملفات.
+
راجع صفحة التابع <code>[[Ruby/Kernel/exec|exec]]</code> لأجل لمزيد من المعلومات حول الصدفة (shell) القياسية.
راجع صفحة <code>spawn</code> لأجل لمزيد من المعلومات بخصوص الصدفة (shell) القياسية.
 
==البنية العامة==
 
<syntaxhighlight lang="ruby">spawn([env,] command... [,options])  → pid
 
spawn([env,] command... [,options])  → pid‎</syntaxhighlight>
 
 
==المعاملات==
 
==المعاملات==
 
===<code>env‎</code>===
 
===<code>env‎</code>===
 
+
بيئة التنفيذ.
 
===<code>command...‎</code>===
 
===<code>command...‎</code>===
 
+
التعليمة المراد تنفيذها.
 
===<code>options‎</code>===
 
===<code>options‎</code>===
 
+
خيارات إضافية للتحكم بالعملية.
 
+
==القيمة المعادة==
==القيمة المُعادة==
+
يعاد معرف العملية المنفذة (pid).
 
 
 
==أمثلة==
 
==أمثلة==
مثال على استخدام التابع <code>spawn‎</code>:
+
مثال على استخدام التابع <code>spawn‎</code>:<syntaxhighlight lang="ruby">pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
<syntaxhighlight lang="ruby">pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
 
 
Process.wait pid
 
Process.wait pid
 
pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
 
pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
 
Process.wait pid‎</syntaxhighlight>
 
Process.wait pid‎</syntaxhighlight>
 
==انظر أيضا==
 
==انظر أيضا==
* التابع <code>[[Ruby/Kernel/sleep|sleep]]</code>: يعلّق التابع sleep المهمة الفرعية (thread) الحالية لعدد من الثواني (والذي قد بكون أي عدد، بما في ذلك <code>Float</code> مع كسور ثوان). ثم يعيد عدد الثواني الفعلي (بالتقريب) الذي نامتها المهمة الفرعية، والذي قد يكون أقل من العدد المطلوب إن استدعت مهمة فرعية أخرى <code>Thread#run</code>. في حال استدعائها دون تمرير أي وسيط، ستقوم sleep() بتنويم المهمة الفرعية إلى الأبد.
+
*التابع <code>[[Ruby/Kernel/exec|exec]]</code>: يستبدل العملية (process) الحالية عبر تشغيل الأمر الخارجي المعطى.
* التابع <code>[[Ruby/Kernel/sprintf|sprintf]]</code>: يعيد التابع sprintf السلسلة النصية الناتجة من تطبيق format_string على الوسائط الإضافية.  داخل سلسلة التنسيق، يتم نسخ كل الأحرف في النتيجة باستثناء تسلسلات الشكل .
+
*التابع <code>[[Ruby/Kernel/system|system]]</code>: ينفذ التعليمة المعطاة في صدفة فرعية (subshell).
 
 
 
==مصادر==
 
==مصادر==
*[http://ruby-doc.org/core-2.5.1/Kernel.html#method-i-spawn قسم التابع spawn‎ في الصنف Kernel‎ في توثيق روبي الرسمي.]
+
*[http://ruby-doc.org/core-2.5.1/Kernel.html#method-i-spawn قسم التابع spawn‎ في الصنف Kernel‎ في توثيق روبي الرسمي.]

المراجعة الحالية بتاريخ 06:41، 6 يناير 2019

ينفذ التابع spawn تعليمة محددة، ثم يعيد معرفها (pid).

البنية العامة

spawn([env,] command... [,options])   pid
spawn([env,] command... [,options])   pid

يشبه التابعُ spawn التابعَ system باستثناء أنّه لا ينتظر إلى أن ينتهي تنفيذ الأمر.

يجب على العملية الأب (parent process) أن تستخدم التابع Process.wait لتحصيل حالة الإنهاء للعملية الفرعية، أو تستخدم Process.detach لتسجيل عدم الاهتمام بحالتها؛ خلاف ذلك، قد يُراكم نظام التشغيل عمليات ميتة (zombie processes).

التابع spawn لديه مجموعة من الخيارات لتحديد خاصيات العملية:

env: hash
name => val يضبط متغيرات البيئة.
name => nil يلغي ضبط متغيرات البيئة.
ينبغي تكون المفاتيح والقيم سلاسل نصية باستثناء nil.
...command
commandline تعليمة نصية تُمرر إلى الصدفة القياسية.
... ,cmdname, arg1 تعليمة وواحد أو أكثر من الوسائط (هذا الشكل لا يستخدم الصدفة).
‎[cmdname, argv0], arg1, ...‎ تعليمة والوسيط argv[0]‎ ووسيط واحد أو أكثر.
ptions: hash
مسح متغيرات البيئة (clearing environment variables)
unsetenv_others => true: مسح متغيرات البيئة باستثناء المحددة من قبل env.
unsetenv_others => false: عدم مسح المتغيرات - الخيار الافتراضي.
process group: (مجموعة العمليات)
pgroup => true or 0: إنشاء مجموعة عمليات جديدة.
pgroup => pgid: الانضمام إلى مجموعة العمليات المحددة.
pgroup => nil: عدم تغيير مجموعة العمليات (الافتراضي).
إنشاء مجموعة عمليات جديدة: ويندوز فقط
new_pgroup => true: العملية الجديدة هي العملية الأصل لمجموعة عمليات جديدة.
new_pgroup => false: عدم إنشاء مجموعة عمليات جديدة (الافتراضي).
اسم المورد (resourcename): هو نواة (core)، معالج (cpu)، بيانات، ...إلخ. انظر التابع Process.setrlimit.
‎:rlimit_resourcename => limit
‎:rlimit_resourcename => [cur_limit, max_limit]‎
umask:
umask => int:
إعادة التوجيه (redirection):
  • المفتاح (key):
FD واصف ملف واحد في العملية الفرعية.
[FD, FD, ...‎] واصفات ملف متعددة في العملية الفرعية.
  • القيمة (value):
FD يعيد التوجيه إلى واصف الملف في العملية الأب.
string يعيد التوجيه إلى الملف مع open(string, "r" or "w"‎)‎.
[string] يعيد التوجيه إلى الملف مع open(string, File::RDONLY)‎.
[string, open_mode] يعيد التوجيه إلى الملف مع open(string, open_mode, 0644)‎.
[string, open_mode, perm] يعيد التوجيه إلى الملف مع open(string, open_mode, perm)‎.
[child, FD:] يعيد التوجيه إلى واصف الملف المعاد توجيهه.
close: يغلق واصف الملف في العملية الفرعية.
واصف الملف FD هو أحد القيم التالية:
in: واصف الملف رقم 0 والذي هو الدخل القياسي.
out: واصف الملف رقم 1 والذي هو الخرج القياسي.
err: واصف الملف رقم 2 والذي هو مجرى الخطأ القياسي.
integer واصف الملف ذو العدد الصحيح المحدد.
io واصف الملف io.fileno.
وراثة واصف الملف: أغلق واصفات الملفات غير الموجَّهة وغير القياسية (مثل 3، و 4، و 5، ...إلخ.) أو لا.
close_others => true: لا تستعمل الواصفات الموروثة.
المجلد الحالي:
chdir => str:
 لا يستخدم الشكل 'cmdname, arg1, ...‎' الصدفة. لكن في بعض أنظمة التشغيل، يتم توفير أوامر مدمجة (built-in) مثل "echo"، المُدمج في ويندوز ، خلافًا للأنظمة لينكس وماك التي يعد فيها أمرًا طبيعيًّا. وهذا يعني أن `Process.spawn 'echo', '%Path%'‎` سيعرض محتويات متغير البيئة `%Path%` على ويندوز، لكن `Process.spawn 'echo', '$PATH'‎` سيطبع '‎$PATH‎' حرفيًّا.

إن كانت القيمة المعطاة للمعامل env جدولًا من النوع Hash، فسيتم تحديث البيئة بواسطة env قبل تنفيذ exec(2)‎ في العملية الفرعية. إن كان لأحد مدخلات المعامل env القيمة nil، فسيُحذَف ذلك المتغير.

# set FOO as BAR and unset BAZ.
pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)

إن كانت القيمة المعطاة للمعامل options جدولًا من النوع Hash، فسيُحدِّد مجموعة العمليات (process group)، وينشئ مجموعة عمليات جديدة، ويحدد الموارد، والمجلد الحالي، ويقوم بتقنيع (umask) وإعادة توجيه العملية الفرعية. ويمكن أيضًا ضبطها لمحو متغيرات البيئة. المفتاح ‎:unsetenv_others في options يؤدي إلى محو متغيرات البيئة فضلًا عن تلك المحددة بواسطة env.

pid = spawn(command, :unsetenv_others=>true) # no environment variable
pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only

يحدد المفتاح ‎:pgroup في الخيارات options مجموعة العملية. يجب أن تساوي القيمة المقابلة true، أو صفرًا، أو عددًا صحيحًا موجبًا، أو القيمة nil. القيمتان true والصفر 0 تجعلان العملية عمليةً قائدةً (process leader) لمجموعة عمليات جديدة. عدد صحيح موجب غير معدوم سيجعل العملية تنضم إلى مجموعة العمليات المعطاة. أما القيمة الافتراضية nil، فستُبقي العملية في نفس مجموعة العمليات.

pid = spawn(command, :pgroup=>true) # process leader
pid = spawn(command, :pgroup=>10) # belongs to the process group 10

المفتاح ‎:new_pgroup في الخيارات options يؤدي إلى تمرير الراية CREATE_NEW_PROCESS_GROUP إلى CreateProcessW()‎، والتي هي واجهة برمجية في أنظمة ويندوز (Windows API). هذا الخيار متاح فقط لنظام التشغيل ويندوز. القيمة true تعني أن العملية الجديدة ستكون العملية الأب لمجموعة العمليات الجديدة. يتم تعطيل CTRL + C في العملية الجديدة. هذه الراية ضرورية للتابع Process.kill(:SIGINT,pid)‎ في العملية الفرعية. قيمة new_pgroup: تساوي false افتراضيًا.

pid = spawn(command, :new_pgroup=>true)  # new process group
pid = spawn(command, :new_pgroup=>false) # same process group

يحدِّد المفتاح ‎:rlimit_foo حدود الموارد. ويجب أن تكون foo إحدى أنواع الموارد مثل core. كما يجب أن تكون القيمة المقابلة إما عددًا صحيحًا، أو مصفوفةً تحتوي على عدد أوعددين صحيحين مثل الوسيطين cur_limit و max_limit في Process.setrlimit.

cur, max = Process.getrlimit(:CORE)
pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary.
pid = spawn(command, :rlimit_core=>max) # enable core dump
pid = spawn(command, :rlimit_core=>0) # never dump core.

يحدد المفتاح ‎:umask في الخيارات options التقنيع (umask).

pid = spawn(command, :umask=>077)

يحدِّد المفتاح ‎:in و out: و err: و integer و io والمصفوفة إعادة توجيه. تحدد إعادة التوجيه واصف ملف (file descriptor) في العملية الابن. على سبيل المثال، يمكن دمج stderr في stdout كما يلي:

pid = spawn(command, :err=>:out)
pid = spawn(command, 2=>1)
pid = spawn(command, STDERR=>:out)
pid = spawn(command, STDERR=>STDOUT)

تحدد مفاتيح الجدول Hash واصف الملف في العملية الفرعية التي بدأها spawn. أما err:، و 2، و STDERR فيعيّنان مجرى الخطأ القياسي (stderr).

تعيّن قيم الجدول Hash واصف ملف في العملية الأب، والتي تستدعي spawn. أما out: و 1 و STDOUT فتحدد مجرى الخرج القياسي (stdout).

في المثال أعلاه، لم يُحدّد مجرى الخرج القياسي في العملية الفرعية. لذلك فهو يرثها من العملية الأب.

يمكن تحديد مجرى الدخل القياسي (stdin) بواسطة in: و 0 و STDIN.

يمكن تحديد اسم ملف كقيمة في الجدول Hash.

pid = spawn(command, :in=>"/dev/null") # read mode
pid = spawn(command, :out=>"/dev/null") # write mode
pid = spawn(command, :err=>"log") # write mode
pid = spawn(command, [:out, :err]=>"/dev/null") # write mode
pid = spawn(command, 3=>"/dev/null") # read mode

بالنسبة إلى stdout و stderr (أو مزيج منهما) ، يتم فتحهما في وضع الكتابة. وإلا فسيُعتمد وضع القراءة. لتحديد رايات وأذونات إنشاء الملفات بشكل صريح، يمكن استخدام مصفوفة.

pid = spawn(command, :in=>["file"]) # read mode is assumed
pid = spawn(command, :in=>["file", "r"])
pid = spawn(command, :out=>["log", "w"]) # 0644 assumed
pid = spawn(command, :out=>["log", "w", 0600])
pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])

تحدد المصفوفة اسم الملف والرايات والأذونات. الرايات قد تكون سلاسل نصية أو أعدادًا صحيحةً. إذا حُذفَت الرايات أو كانت قيمتها nil، فستُستعمَل القيمة File::RDONLY الافتراضية. يجب أن يكون الإذن عددًا صحيحًا. إذا تم حذف الإذن أو كان يساوي nil، فسيتم اعتماد القيمة 0644 الافتراضية. إذا تم تحديد مصفوفة من كائنات IO ومن الأعداد الصحيحة كمفتاح للجدول Hash، فسيتم إعادة توجيه جميع العناصر.

# stdout and stderr is redirected to log file.
# The file "log" is opened just once.
pid = spawn(command, [:out, :err]=>["log", "w"])

هناك طريقة أخرى لدمج عدة واصفات ملفات وهي [‎:child، fd]. والتي تعني واصف الملف في العملية الفرعية. وهو مختلف عن fd. على سبيل المثال، تعني err =>:out إعادة توجيه المجرى stderr للعملية الفرعية إلى المجرى stdout للعملية الأب. ولكن ‎:err => [:child،:out]‎ تعني إعادة توجيه المجرى stderr للعملية الفرعية إلى المجرى stdout للعملية الفرعية نفسها، إذ سيكونان مختلفين إذا أُعيد توجيه المجرى stdout في العملية الفرعية على النحو التالي.

# stdout and stderr is redirected to log file.
# The file "log" is opened just once.
pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out])

يمكن استخدام [‎:child، :out] لدمج المجرى stderr في المجرى stdout في IO.popen. في هذه الحالة، يعيد IO.popen توجيه المجرى stdout إلى أنبوب (pipe) في العملية الفرعية، إذ تشير [‎:child ، :out] إلى المجرى stdout المعاد توجيهه.

io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]])
p io.read #=> "out\nerr\n"

يحدد المفتاح ‎:chdir في options المجلد الحالي.

pid = spawn(command, :chdir=>"/var/tmp")

تغلق spawn افتراضيًّا جميع الواصفات غير المحددة وغير القياسية. الواصفات "القياسية" هي 0 و 1 و 2. يتم تحديد هذا السلوك بواسطة الخيار: ‎:close_others. الخيار ‎:close_others لا يؤثر على الواصفات القياسية التي يتم إغلاقها إلا في حالة تم تحديد :close بشكل صريح.

pid = spawn(command, :close_others=>true)  # close 3,4,5,... (default)
pid = spawn(command, :close_others=>false) # don't close 3,4,5,...

قيمة ‎:close_others تساوي true بشكل افتراضي، بالنسبة للتابع spawn و IO.popen. لاحظ أن واصفات الملفات التي تم تعيين الراية close-on-exec لها ستُغلق بغض النظر عن الخيار close_others. لذلك يمكن استخدام التابع IO.pipe والتابع spawn مثل التابع IO.popen.

# similar to r = IO.popen(command)
r, w = IO.pipe
pid = spawn(command, :out=>w)   # r, w is closed in the child process.
w.close

يتم تحديد close: كقيمة في الجدول Hash لإغلاق واصف ملف بشكل فردي.

f = open(foo)
system(command, f=>:close)        # don't inherit f.

إذا كانت هناك حاجة إلى توريث واصف الملف، فيمكن استخدام io => io.

# valgrind has --log-fd option for log destination.
# log_w=>log_w indicates log_w.fileno inherits to child process.
log_r, log_w = IO.pipe
pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w)
log_w.close
p log_r.read

من الممكن أيضًا تبادل واصفات الملفات.

pid = spawn(command, :out=>:err, :err=>:out)

تحدد مفاتيح الجدول Hash واصفات الملفات في العملية الفرعية بينما تحدد قيم الجدول Hash واصفات الملفات في العملية الأب. بناءً على ذلك، يحدد المثال أعلاه تبادل المَجرّيين stdout و stderr. داخليًا، يستخدم spawn واصف ملف إضافي لحل هذا التعيين الدوري لواصفات الملفات.

راجع صفحة التابع exec لأجل لمزيد من المعلومات حول الصدفة (shell) القياسية.

المعاملات

env‎

بيئة التنفيذ.

command...‎

التعليمة المراد تنفيذها.

options‎

خيارات إضافية للتحكم بالعملية.

القيمة المعادة

يعاد معرف العملية المنفذة (pid).

أمثلة

مثال على استخدام التابع spawn‎:

pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
Process.wait pid
pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
Process.wait pid

انظر أيضا

  • التابع exec: يستبدل العملية (process) الحالية عبر تشغيل الأمر الخارجي المعطى.
  • التابع system: ينفذ التعليمة المعطاة في صدفة فرعية (subshell).

مصادر