/usr/bin/env أسئلة بخصوص كوخ خط pecularities
-
20-08-2019 - |
سؤال
الأسئلة:
- ماذا نواة تفعل إذا كنت عصا قذيفة النصي في كوخ الخط ؟
- كيف نواة تعرف أي مترجم على الاطلاق ؟
تفسير:
مؤخرا أردت أن أكتب التفاف حول /usr/bin/env لأن CGI بيئة لا تسمح لي أن تعيين المسار متغير, إلا عالميا (والتي بالطبع سيء!).
حتى ظننت, "حسنا.دعونا تعيين PREPENDPATH وتعيين المسار في التفاف حول الحياة الفطرية.".مما أدى النصي (يسمى هنا env.1) يشبه هذا:
#!/bin/bash
/usr/bin/env PATH=$PREPENDPATH:$PATH $*
التي يبدو أن العمل.راجعت كم هم كل من رد بعد وضع PREPENDPATH:
$ which /usr/bin/env python
/usr/bin/env
/usr/bin/python
$ which /usr/bin/env.1 python
/usr/bin/env
/home/pi/prepend/bin/python
نظرة على الاطلاق مثالية!جيد جدا حتى الآن.ولكن انظر ماذا يحدث "مرحبا العالم!".
# Shebang is #!/usr/bin/env python
$ test-env.py
Hello World!
# Shebang is #!/usr/bin/env.1 python
$ test-env.1.py
Warning: unknown mime-type for "Hello World!" -- using "application/*"
Error: no such file "Hello World!"
أعتقد أنا في عداد المفقودين شيء جميل الأساسية عن يونيكس.
أنا جدا المفقودة حتى بعد النظر في التعليمات البرمجية المصدر الأصلي env.فإنه يحدد البيئة تطلق برنامج (أو هكذا يبدو لي).
المحلول
أولا وقبل كل شيء ، يجب أن نادرا جدا استخدام $*
و يجب دائما تقريبا استخدام "$@"
بدلا من ذلك.هناك عدد من الأسئلة هنا حتى التي تشرح وعموميات من السبب.
الثانية - env
الأمر قد يستخدم.واحد هو طباعة البيئة الحالية ؛ والآخر هو السيطرة تماما على بيئة الأمر عندما يتم تشغيله.الاستخدام الثالث الذي كنت يدل إلى تعديل البيئة ، ولكن بصراحة هناك حاجة لذلك - قذائف قادرة تماما على التعامل مع ذلك لك.
الوضعية 1:
env
الوضعية 2:
env -i HOME=$HOME PATH=$PREPENDPATH:$PATH ... command args
هذا الإصدار يلغي كل ورثت متغيرات البيئة و يعمل command
مع دقة البيئة التي وضعتها ENVVAR=قيمة الخيارات.
النمط الثالث - تعديل البيئة - هو أقل أهمية لأنه يمكنك أن تفعل ذلك بشكل جيد مع العادية (المتحضر) قذائف.(التي تعني "لا" ج "شل" - مرة أخرى ، هناك أسئلة أخرى بشأن ذلك مع الإجابات التي تفسر ذلك.) على سبيل المثال ، يمكنك جيدا القيام به:
#!/bin/bash
export PATH=${PREPENDPATH:?}:$PATH
exec python "$@"
هذا تصر على أن $PREPENDPATH
يتم تعيين غير فارغة في البيئة ، ومن ثم prepends إلى $PATH
, و الصادرات مسار جديد الإعداد.ثم باستخدام هذا الطريق الجديد, ينفذ python
برنامج مع الحجج ذات الصلة.على exec
يستبدل قذيفة النصي مع python
.لاحظ أن هذا يختلف تماما عن:
#!/bin/bash
PATH=${PREPENDPATH:?}:$PATH exec python "$@"
ظاهريا هذا هو نفسه.إلا أن هذا سيتم تنفيذ python
الاطلاع على القائمة من قبل الطريق ، وإن كان ذلك مع قيمة جديدة من مسار في عملية البيئة.لذلك ، في سبيل المثال ، كنت في نهاية المطاف تنفيذ الثعبان من /usr/bin
وليس واحد من /home/pi/prepend/bin
.
في الوضع الخاص بك, أنا ربما لا تستخدم env
و أن مجرد استخدام البديل المناسب من النص مع صريح التصدير.
على env
الأمر غير عادية لأنها لا تعترف مزدوجة اندفاعة إلى خيارات منفصلة عن بقية الأوامر.هذا هو في جزء منه لأنه لا يأخذ العديد من الخيارات ، في جزء منه لأنه ليس من الواضح ما إذا كان ENVVAR=قيمة الخيارات يجب أن تأتي قبل أو بعد double dash.
في الحقيقة لدي مجموعة من البرامج النصية تشغيل (إصدارات مختلفة من) خادم قاعدة البيانات.هذه البرامج النصية حقا استخدام env
(و مجموعة نابعة من البرامج) للسيطرة على البيئة من الملقم:
#!/bin/ksh
#
# @(#)$Id: boot.black_19.sh,v 1.3 2008/06/25 15:44:44 jleffler Exp $
#
# Boot server black_19 - IDS 11.50.FC1
IXD=/usr/informix/11.50.FC1
IXS=black_19
cd $IXD || exit 1
IXF=$IXD/do.not.start.$IXS
if [ -f $IXF ]
then
echo "$0: will not start server $IXS because file $IXF exists" 1>&2
exit 1
fi
ONINIT=$IXD/bin/oninit.$IXS
if [ ! -f $ONINIT ]
then ONINIT=$IXD/bin/oninit
fi
tmpdir=$IXD/tmp
DAEMONIZE=/work1/jleffler/bin/daemonize
stdout=$tmpdir/$IXS.stdout
stderr=$tmpdir/$IXS.stderr
if [ ! -d $tmpdir ]
then asroot -u informix -g informix -C -- mkdir -p $tmpdir
fi
# Specialized programs carried to extremes:
# * asroot sets UID and GID values and then executes
# * env, which sets the environment precisely and then executes
# * daemonize, which makes the process into a daemon and then executes
# * oninit, which is what we really wanted to run in the first place!
# NB: daemonize defaults stdin to /dev/null and could set umask but
# oninit dinks with it all the time so there is no real point.
# NB: daemonize should not be necessary, but oninit doesn't close its
# controlling terminal and therefore causes cron-jobs that restart
# it to hang, and interactive shells that started it to hang, and
# tracing programs.
# ??? Anyone want to integrate truss into this sequence?
asroot -u informix -g informix -C -a dbaao -a dbsso -- \
env -i HOME=$IXD \
INFORMIXDIR=$IXD \
INFORMIXSERVER=$IXS \
INFORMIXCONCSMCFG=$IXD/etc/concsm.$IXS \
IFX_LISTEN_TIMEOUT=3 \
ONCONFIG=onconfig.$IXS \
PATH=/usr/bin:$IXD/bin \
SHELL=/usr/bin/ksh \
TZ=UTC0 \
$DAEMONIZE -act -d $IXD -o $stdout -e $stderr -- \
$ONINIT "$@"
case "$*" in
(*v*) track-oninit-v $stdout;;
esac
نصائح أخرى
يجب أن تقرأ بعناية مقالة ويكيبيديا عن كوخ.
عندما يرى النظام الرقم السحري المقابلة تلك لا execve
على مسار معين بعد كوخ ويعطي السيناريو نفسه حجة.
البرنامج النصي الخاص بك فشل لأن الملف تعطي (/usr/bin/env.1
) لا قابل للتنفيذ, ولكن يبدأ بنفسه قبل كوخ....
من الناحية المثالية, هل يمكن حلها باستخدام... env
في السيناريو الخاص بك مع هذا الخط بمثابة كوخ:
#!/usr/bin/env /usr/bin/env.1 python
فإنه لن ينجح ولو على لينكس كما يعامل "/usr/bin/env.1 python
"كمسار (لا تقسيم الحجج)
وبالتالي فإن الطريقة الوحيدة أرى أن الكتابة الخاصة بك env.1
في ج
تحرير:يبدو أن لا أحد صدق بأن لي ^^, حتى لقد كتب بسيطة القذرة env.1.c
:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
const char* prependpath = "/your/prepend/path/here:";
int main(int argc, char** argv){
int args_len = argc + 1;
char* args[args_len];
const char* env = "/usr/bin/env";
int i;
/* arguments: the same */
args[0] = env;
for(i=1; i<argc; i++)
args[i] = argv[i];
args[argc] = NULL;
/* environment */
char* p = getenv("PATH");
char* newpath = (char*) malloc(strlen(p)
+ strlen(prependpath));
sprintf(newpath, "%s%s", prependpath, p);
setenv("PATH", newpath, 1);
execv(env, args);
return 0;
}