آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

مشکل X-Y

XyProblem

مشکل X-Y چنانکه گاهی اوقات XyProblem نامیده شده، هذیانی است که برای افراد در هر دو طرف متقاضی کمک و ارائه دهنده کمک، منجر به اتلاف وقت و انرژی بسیار زیاد می‌گرد. این مورد غالباً به صورتی مشابه این پیش می‌رود:

  • کاربر می‌خواهد X را انجام بدهد.
  • کاربر نمی‌داند X را چطور انجام بدهد، اما فکر می‌کند اگر آنها فقط بتوانندانجام Y را اداره کنند، چشم بسته به یک جواب می‌رسند.
  • کاربر چگونگی انجام Y را هم نمی‌داند.
  • کاربر برای کمک در مورد Y پرسش می‌کند.
  • دیگران سعی می‌کنند در مورد Y به کاربر کمک کنند، اما گیج می‌شوند زیرا Y که می‌خواهند آن را حل کنند به نظر می‌رسد مشکل عجیبی است.
  • پس از فعل و انفعال زیاد و اتلاف وقت، سرانجام روشن می‌گردد که کاربر حقیقتاً در مورد X کمک می‌خواهد، و آن Y هم راه حل مناسبی برای X نبوده.

مشکل موقعی رخ می‌دهد که اشخاص خط فکری خودشان را گرفته و شیفته یک رویکرد می‌شوند و از برگشتن به یک مرحله قبل ناتوان می‌گردند. این افراد با داشتن یک نگاه جدید از منظر بزرگتر، شاید راه برگشت به X و ادامه جستجو برای راه حل‌های جایگزین را پیدا کنند.

این یک نمونه است.

<n00b> چگونه می‌توانم سه کاراکتر انتهای نام فایل را نمایش بدهم؟

<feline> اگر آنها در یک متغیر باشند با:  ‎echo ${foo: -3}‎
<feline> چرا 3 کاراکتر؟ واقعاًچه می‌خواهی؟
<feline> پسوند را می‌خواهی؟

<n00b> بله.

<feline> پس آنچه را می‌خواهی بپرس!
<feline> تضمینی وجود ندارد که هر نام فایل پسوند سه کاراکتری داشته باشد،
<feline> بنابراین گرفتن کورکورانه سه کاراکتر مشکل را حل نمی‌کند.
<feline> از این استفاده کن ‎echo ${foo##*.}‎

یک مثال دیگر:

RikusW> فرض کنید من یک نام فایل در‎ $1‎ دارم، چطور می‌توانم اندازه آن را به دست آورم؟

greycat> چرا؟

erUSUL> با ‎du $file‎

RikusW> تشکر

erUSUL> با ‎du "$file"‎ هم

RikusW> فکرش را نکرده‌ای ... :)

greycat> پاسخهای لفظی به پرسشهای نامناسب می‌تواند خطرناک باشد.
greycat> چرا آن اندازه را می‌خواهی؟ مقصود چیست؟

RikusW> با ‎`du $1`‎ ممکنه؟
RikusW> نیاز برای نوشتن یک اسکریپت برای dd و قسمت کردن خروجی به 512k و  md5sum آن...

erUSUL> ‏RikusW: چی؟ بعداً می‌خواهی با آن اندازه کاری انجام بدهی؟

greycat> شما چی می‌خواهی؟

RikusW> دستور dd وقتی به انتها می‌رسد 1 را برگشت نمی‌دهد...

greycat> ... چرا یک md5 منفرد برای کل آن چیز نمی‌گیرید؟

RikusW> من یک فایل خراب 500 مگا بایتی دارم....
RikusW> و یک ارتباط کند

greycat> ‏rsync.
greycat> دیگه!

و یک مثال دیگر:

<lhunath> موقع شروع یک پردازش از پوسته ، پردازش، gid پوسته را به ارث می‌برد - من در نظر دارم پردازشی را با یک GID غیر از شماره شنایی گروه خودم شروع کنم، بنابراین فرض کردم اول بایدبه گروه جدید newgrp کنم و  سپس پردازش را شروع کنم - اما اجرای  ‎newgrp audio‎  به عنوان غیر-root این خطا را می‌دهد: ‎Can not execute bash: No such file or directory                            
‎<lhunath>‎ اگر چه ‎newgrp - audio‎ کار می‌کند، اما من نمی‌توانم برای شروع یک پردازش معین با یک GID متفاوت از این در یک اسکریپت پوسته استفاده نمایم، چون یک پوسته فرعی تولید می‌کند

<greycat> شما *واقعاً* سعی دارید چه کار کنید؟

<lhunath> سعی در شروع wine با شماره شناسایی گروه audio

‎<greycat>‎ ‏lhunath: خُب... daemontools یک برنامه setuidgid را شامل می‌شود که می‌تواند آن را انجام بدهد، اما برای اجرای آن شما باید به عنوان root اقدام کنید، و سپس  یک حساب کاربری تعریف کنید که گروه اولیه آن دارای  GID مورد نظر شما باشد.
<greycat> من شک دارم که آنچه شما می‌خواهید انجام بدهید *واقعاً* « وادار به کارکردن audio در wine» باشد. به این معنی که احتمالاً بخواهید خودتان را به گروه «audio» در  ‎/etc/group‎ اضافه کنید، و logout و برگشت.

<lhunath> په هه هه، اگر فقط به آن آسانی بود. نه، آنچه من *واقعاً* سعی می‌کنم انجام بدهم به دست آوردن rlimits است که در pam برای ‎@audio‎ تنظیم کنم تا به پردازش wineserver اِعمال گردد به طوری که بتواند از sched_fifo  استفاده کند، برای آنکه اولویت بالاتر به نخ‌های audio  جهت بازی‌هایی که آن را درخواست می‌کنند بدهد. برای اینکه wineserver قادر باشد از rlimits استفاده کند، نیاز به داشتن یک gid از ‎@audio‎ دارد که من در ‎/etc/security/limits.conf‎ تعریف نموده‌ام

<greycat> شما که حقیقتاً گمان نمی‌کنی rlimits موقعی که یک پردازش با یک UID/GID مخصوص فراخوانی بشود به طور جادویی ظاهر شود، گمان می‌کنی؟
<greycat> rlimits داخل *خود* پردازش شما تنظیم می‌شود و سپس موقعی که شما ‎fork/exec‎ می‌کنید به فرزندان شما به ارث می‌رسد.
<greycat> تنها موارد خاصی فایلهای پیکربندی ‎pam.d‎ را می‌خوانند -- مواردی که به libpam لینک می‌شوند.
<greycat> مانند ‎/bin/login or /usr/sbin/sshd‎

‎‎<lhunath>‎ ‏greycat: آیا اگر تعریف می‌کردم
 ‎'@audio          -       rtprio          90' in /etc/security/limits.conf ;x‎

<greycat> lhunath: فکر می‌کنید کدام پردازش آن فایل را می‌خواند؟

‎<lhunath>‎ ‏pam
‎<lhunath>‎ ‏hrm.

<greycat> lhunath: و شما فکر می‌کنید که «wine» با libpam لینک می‌شود؟
<greycat> لازم است شما محدودیت‌هایی را که می‌خواهید تنظیم کنید، *و آنوقت* برنامه‌ای را که می‌خواهید اجرا کنید.
<greycat> آنها را به ارث می‌برد.
<greycat> من همیشه مواردی مانند این را انجام می‌دهم:  
‏شروع Freenet node‏‎ su --> ulimit -v whatever --> su - freenet   ---->  ‎ 
<greycat> معمولاً ‎exec su - freenet‎ به طوری که اگر/وقتی پردازش freenet منقضی شود یک پوسته ‎ raw roo‎t پاکیزه نشده رها می‌شود

<lhunath> هه.

<goldfish> دلپذیر

<greycat> ببین، به *این* دلیل است که من مواردی مانند «واقعاً در تلاش برای انجام چه کاری هستید» را می‌پرسم

این یکی خیلی زیاد پیش می‌آید. جداً دست کم یکبار در هفته، به موقعی بازمی‌گردد که Gentoo محبوب‌تر بود:

(مترجم: این مثال آخری را ترجمه نکردم چون نمونه‌های بومی مشکل X-Y در انجمن‌های فارسی به وفور دیده می‌شود.)

<chron> i'm editting a sed stream like:  sed 's/^/blah/'
<chron> but i want to replace with 'blah/' instead of 'blah'
<chron> editting a stream*

<greycat> blah\/ or use a different separator

<_matt> blah\//

<chron> thanks
<chron> i'm trying to ls a directory, and every file or folder that shows in ls, i want it to come out like file1 file2 file3  (all in one line)
<chron> instead of columns or list

<greycat> echo *

<trash> chron: echo dir/*

<chron> i'm trying to compare 2 files: file1 and file2, if there is any matching line in file1 from file2, i want it gone from file1

<greycat> !faq subtract
->#bash http://wooledge.org/mywiki/BashFaq#faq36 -- How can I get all lines that are: in both of two files (set intersection) or in only one of two files (set subtraction).

<trash> !bashphorism2
->#bash The questioner will keep changing the original question until it drives the helpers in the channel insane.

* greycat goes out on a limb and guesses that the actual question is "I want to synchronize a directory against another directory"

<chron> no
<chron> i know what i'm doing, i swear
<chron> lol

<trash> I swear you don't.

<chron> cool worked, thanks guys
<chron> i have a file with <package>-<ver> in a list (separate lines), for example: gnu-netcat-0.7.1, and i want to remove -<ver>
<chron> gnu-netcat-0.7.1 becomes gnu-netcat

<Knirch> !pe
->#bash Parameter Expansion. Expressions like ${foo%.mp3} and so on -- see man bash, and then search for Parameter Expansion. See also, http://wooledge.org/mywiki/BashFaq#faq74 and http://tiswww.tis.case.edu/~chet/bash/bashref.html#SEC30

<greycat> chron: ${foo%-*}
<greycat> !pe
->#bash Parameter Expansion. Expressions like ${foo%.mp3} and so on -- see man bash, and then search for Parameter Expansion. See also, http://wooledge.org/mywiki/BashFaq#faq74 and http://tiswww.tis.case.edu/~chet/bash/bashref.html#SEC30

<chron> and that will work even with something like gnu-netcat-0.7.1 ?
<chron> when it has the hyphen after 'gnu'

<greycat> !pe
->#bash Parameter Expansion. Expressions like ${foo%.mp3} and so on -- see man bash, and then search for Parameter Expansion. See also, http://wooledge.org/mywiki/BashFaq#faq74 and http://tiswww.tis.case.edu/~chet/bash/bashref.html#SEC30

<chron> ok ok

<savetheWorld> foo=gnu-netcat-0.7.1;  echo ${foo/-[0-9]*/}

<greycat> savetheWorld: stupid.

* savetheWorld humbly accepts greycat's gentle critique, begs forgiveness and asks for more information

<chron> how do you do it for every line?

<greycat> !faq 1
->#bash http://wooledge.org/mywiki/BashFaq#faq1 -- How can I read a file line-by-line?

<greycat> savetheWorld: foo=glibc-2.5-2.5.1
<greycat> in that case, you want glibc-2.5 to be the output, but yours fails.

<savetheWorld> greycat: but I just tested it.
<savetheWorld> foo=glibc-2.5-2.5.1;  echo ${foo/-[0-9]*/}
<savetheWorld> glibc

<greycat> savetheWorld: and that's wrong.

<chron> it's not glibc-2.5

<savetheWorld> ah, rats
<savetheWorld> hmm - right end anchor.... ah, first dash traveling left from the right hand end.

<greycat> which is precisely what ${foo%-*} does

<savetheWorld> ah, didn't see you post that the first time.

<greycat> it was delayed by some lag

<savetheWorld> and % is non greedy, %% is greedy.
<savetheWorld> right?

<igli> yup

<savetheWorld> tx

<chron> ok greycat was right, but i needed savetheWorld's solution

<greycat> !bashphorism1
->#bash the questioner's first description of the problem/question will be misleading.

<chron> lol because some packages look like blah-2.5-r4
<chron> thanks both

<greycat> Has to be a Gentoo user.

<chron> lol
<chron> quit being so uncanny

<igli> chron: what are you working on?

<chron> emerging all packages in a category
<chron> that are not already merg'd

<igli> all in the whole cat?

<greycat> and the reason you can't just type "emerge blah-2.5-r4" is...?

<trash> he has to type emerge =blah-version

<chron> not only that but

<greycat> and the reason you can't just type "emerge =blah-2.5-r4" is...? ;-)

<igli> he needs the list first

<chron> i want to get ones that aren't already merg'd

<trash> chron: just add -u

<greycat> !xy
->#bash http://wooledge.org/mywiki/XyProblem

<chron> and i need to get that not-already-merged list
<chron> into /etc/portage/package.keywords
<chron> i know what i'm doing :>

<igli> cd /usr/portage/"$cat"; list=($(echo *))

<greycat> You're a gentoo user.  By definition, you don't have a clue what you're doing.

<greycat> igli: you mean list=(*)

<savetheWorld> "you keep saying that.   I do not think it means what you think it means"..... TPB.

<chron> but my /etc/portage/package.keywords looks very funny with massive comments

<igli> god yes, sorry, just woke up

<chron> no gentoo means i know what i'm doing

<trash> chron: LOL
<trash> that was a good one.

<savetheWorld> Inconceivable!

<chron> please don't tell me you use debian
<chron> else i'd be laughing for days

<greycat> Now that's a case where LOL was probably literal.

<igli> chron: don't get into this seriously
<igli> #friendly-coders when they've mauled you enuff chron
<igli> ;)

<chron> well i know what i'm doing, and it's already in progress :>

<greycat>    --noreplace (-n)
<greycat>           Skips the packages specified on the command-line that have
<greycat>           already been installed.

<chron> yea that's the solution i'm using when i'm doing actually merger
<chron> last step :)

<igli> cd /usr/portage/"$cat"; list=(*); emerge -n ${list[@]}
<igli> cd /usr/portage/"$cat"; list=(*); emerge -n "${list[@]}" # sorry

<greycat> or just cd /usr/portage/"$cat" && emerge -n *

<igli> heh :)

<greycat> but hey, that would be too obvious and simple!

<igli> "" not needed in gentoo, but best to be safe

<chron> ok i can use that as my last step

<greycat> us poor ignorant Debian and BSD users can't handle his Gentoo elitism.

<igli> chill out greycat :)

<chron> but what i did to get the list in the first place was echo *

<igli> well do that instead

<chron> cd /usr/portage/$cat && emerge -n $whateverthatgotechoed
<chron> lolz

<igli> use *

<chron> or i can just copy and paste what i echo *'d

<greycat> emerge -n *

<chron> ah

<igli> indeed

<trash> indeed lolZ

<chron> lolZ

<igli> hehe that is hilarious

XyProblem (آخرین ویرایش ‎2013-03-19 06:47:47‎ توسط 109-224-132-97)