কীভাবে ওএস.সিস্টেম () কল এড়ানো যায়?


123

ওএস.সিস্টেম () ব্যবহার করার সময় প্রায়শই ফাইলের নাম এবং অন্যান্য আর্গুমেন্টগুলি কমান্ডের প্যারামিটার হিসাবে পাস করা থেকে বাঁচতে হয়। কিভাবে আমি এটি করতে পারব? সাধারণত এমন কিছু যা একাধিক অপারেটিং সিস্টেম / শেলগুলিতে কাজ করবে তবে বিশেষত ব্যাশের জন্য।

আমি বর্তমানে নিম্নলিখিতগুলি করছি, তবে আমি নিশ্চিত যে এর জন্য অবশ্যই একটি লাইব্রেরি ফাংশন থাকতে হবে বা কমপক্ষে আরও মার্জিত / শক্তিশালী / দক্ষ বিকল্প থাকতে হবে:

def sh_escape(s):
   return s.replace("(","\\(").replace(")","\\)").replace(" ","\\ ")

os.system("cat %s | grep something | sort > %s" 
          % (sh_escape(in_filename), 
             sh_escape(out_filename)))

সম্পাদনা: আমি উদ্ধৃতি ব্যবহারের সহজ উত্তরটি গ্রহণ করেছি, জানি না কেন আমি এটি ভেবে দেখিনি; আমি অনুমান করি কারণ আমি উইন্ডোজ থেকে এসেছি যেখানে 'এবং "কিছুটা আলাদা আচরণ করে।

সুরক্ষা সম্পর্কে, আমি উদ্বেগটি বুঝতে পারি, তবে, এই ক্ষেত্রে আমি ওএস.সিস্টেম () সরবরাহ করে এমন একটি দ্রুত এবং সহজ সমাধানে আগ্রহী এবং স্ট্রিংগুলির উত্স হয় ব্যবহারকারী দ্বারা উত্পাদিত হয় না বা কমপক্ষে একটি দ্বারা প্রবেশ করা হয় না বিশ্বস্ত ব্যবহারকারী (আমি)


1
সুরক্ষা ইস্যু থেকে সাবধান! উদাহরণস্বরূপ যদি out_filename foo.txt হয়; rm -rf / দূষিত ব্যবহারকারী শেল দ্বারা সরাসরি ব্যাখ্যা করা আরও কমান্ড যুক্ত করতে পারে।
স্টিভ গ্যারি

6
ওএস.সিস্টেম ব্যতীত এটি দরকারী, এমন পরিস্থিতিতে যেখানে সাবপ্রসেস এমনকি কোনও বিকল্পও নয়; যেমন শেল স্ক্রিপ্ট তৈরি করা।

একটি আদর্শ sh_escapeফাংশন ;স্থান এবং স্থানগুলি থেকে বেরিয়ে আসবে এবং সুরক্ষার সমস্যাটিকে সাদামাটা কিছু জাতীয় ফাইল তৈরি করে সরিয়ে ফেলবে foo.txt\;\ rm\ -rf\ /
টম

প্রায় সব ক্ষেত্রেই আপনার ওএস.সিস্টেম নয় সাব-প্রসেস ব্যবহার করা উচিত। ওএস.সিস্টেমকে কল করা কেবল একটি ইনজেকশন অ্যাটাকের জন্য বলছে।
অ্যালিউরকোড

উত্তর:


84

এটি আমি ব্যবহার করি:

def shellquote(s):
    return "'" + s.replace("'", "'\\''") + "'"

শেলটি সর্বদা একটি উদ্ধৃত ফাইলের নাম গ্রহণ করবে এবং এটি প্রোগ্রামে প্রশ্নবিদ্ধ করার আগে পার্শ্ববর্তী উদ্ধৃতিগুলি সরিয়ে ফেলবে। উল্লেখযোগ্যভাবে, এটি ফাইলের নামগুলিতে সমস্যাগুলি এড়ায় যা স্পেস বা অন্য কোনও ধরণের বাজে শেল মেটাচার্যাক্টর ধারণ করে।

আপডেট : আপনি যদি পাইথন ৩.৩ বা তার পরে ব্যবহার করেন তবে নিজের রোলিংয়ের পরিবর্তে shlex.quote ব্যবহার করুন।


7
@ পিক্সেলবিট: ঠিক এই কারণেই তিনি তার একক উদ্ধৃতি বন্ধ করেন, পালিয়ে যাওয়া আক্ষরিক একক উক্তি যোগ করেন এবং তারপরে আবার তার একক উদ্ধৃতি আবার খোলে।
lhunath

4
যদিও এটি শেলকোট ফাংশনটির পক্ষে খুব কমই দায়বদ্ধ, তবে এটি মনে রাখা আকর্ষণীয় হতে পারে যে যদি এই ফাংশনের রিটার্ন মানটির ঠিক আগে কোনও অব্যক্ত ব্যাকস্ল্যাশ উপস্থিত হয় তবে এটি ব্যর্থ হবে। মনোবল: নিশ্চিত হয়ে নিন যে আপনি কোডটিতে এটি ব্যবহার করেছেন যা আপনি নিরাপদ হিসাবে বিশ্বাস করতে পারেন - (যেমন হার্ডকোডযুক্ত কমান্ডগুলির অংশ) - এটি অন্য অনাবৃত ব্যবহারকারী ইনপুটটিতে যুক্ত করবেন না।
lhunath

10
মনে রাখবেন যে আপনার যদি একেবারে শেল বৈশিষ্ট্যগুলির প্রয়োজন না হয় তবে আপনার পরিবর্তে সম্ভবত জেমির পরামর্শটি ব্যবহার করা উচিত।
lhunath

6
এর অনুরূপ কিছুটি এখন সরকারীভাবে shlex.quote হিসাবে উপলব্ধ
জানুস ট্রয়লসেন

3
এই উত্তরে প্রদত্ত ফাংশন শেলের উদ্ধৃতি দেওয়ার চেয়ে shlexবা আরও ভাল কাজ করে pipes। এই অজগর মডিউলগুলি ভ্রান্তভাবে ধরে নিয়েছে যে বিশেষ অক্ষরগুলি কেবলমাত্র এমন একটি জিনিস যা উদ্ধৃত করা দরকার, যার অর্থ শেল কীওয়ার্ডগুলি (যেমন time, caseবা while) পার্স হবে যখন সেই আচরণটি প্রত্যাশিত হয় না। সেই কারণেই আমি এই উত্তরে একক-উদ্ধৃতি রুটিন ব্যবহার করার পরামর্শ দেব, কারণ এটি "চতুর" হওয়ার চেষ্টা করে না সুতরাং সেই নির্বিকার প্রবণতাগুলির ক্ষেত্রে না হয়।
ব্যবহারকারী 3035772

157

shlex.quote() অজগর 3 থেকে আপনি যা চান তা করে।

( pipes.quoteপাইথন 2 এবং পাইথন 3 উভয়কে সমর্থন করার জন্য ব্যবহার করুন )


এছাড়াও আছে commands.mkarg। এটি একটি শীর্ষস্থানীয় স্থান (উদ্ধৃতিগুলির বাইরে) যুক্ত করে যা কাঙ্ক্ষিত হতে পারে বা নাও পারে their এটি আকর্ষণীয় যে কীভাবে তাদের বাস্তবায়ন একে অপরের থেকে একেবারে আলাদা এবং গ্রেগ হিউগিলের উত্তরের চেয়েও জটিল।
লরেন্স গনসাল্ভেস

3
কোনও কারণে পাইপ মডিউলের জন্য স্ট্যান্ডার্ড লাইব্রেরি ডকুমেন্টেশনpipes.quote দ্বারা উল্লেখ করা হয়নি
দিন

1
উভয়ই অননুমোদিত; command.mkarg3.x এ অবচয় এবং সরানো হয়েছে, পাইপস.কোট রয়ে গেছে।
বেনি চেরনিয়াভস্কি-পাসকিন

9
সংশোধন: আনুষ্ঠানিকভাবে shlex.quote()3.3 হিসাবে নথিভুক্ত , pipes.quote()সামঞ্জস্যের জন্য রক্ষিত [ bugs.python.org/issue9723]
বেনি

7
পাইপগুলি উইন্ডোজে কাজ করে না - ডাবল কোট যুক্ত একক কোট যুক্ত করে।
Nux

58

সম্ভবত আপনার ব্যবহারের নির্দিষ্ট কারণ রয়েছে os.system()। তবে না হলে আপনার সম্ভবত subprocessমডিউলটি ব্যবহার করা উচিত । আপনি পাইপগুলি সরাসরি উল্লেখ করতে পারেন এবং শেলটি ব্যবহার এড়াতে পারেন।

নীচে PEP324 থেকে এসেছে :

Replacing shell pipe line
-------------------------

output=`dmesg | grep hda`
==>
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

6
subprocess(বিশেষত check_callইত্যাদির সাথে) প্রায়শই নাটকীয়ভাবে উচ্চতর হয় তবে কয়েকটি ক্ষেত্রে এমন রয়েছে যেখানে শেল পালানো এখনও কার্যকর। যখন আমি এসএসএস রিমোট কমান্ডগুলি চালাচ্ছি তখন আমি যেটির মধ্যে প্রধান চালাচ্ছি is
ক্রেগ রিঞ্জার

@ ক্রেইগরিঞ্জার, হ্যাঁ, এসএসএস রিমোটিংই আমাকে এখানে এনেছে। : পিআই ইচ্ছুক ssh এখানে সাহায্য করার কিছু ছিল।
জার্জেন এ। এয়ারহার্ড

@ জারজেনা.এরহার্ড এটির মতামতটি অদ্ভুত বলে মনে হচ্ছে যে এর কোনও --execvp- রিমোট বিকল্প নেই (বা সেভাবে ডিফল্টরূপে কাজ করুন)। খোলের মাধ্যমে সবকিছু করা আনাড়ি এবং ঝুঁকিপূর্ণ বলে মনে হয়। OTOH, ssh অদ্ভুত কৌতূহলে পূর্ণ, প্রায়শই "সুরক্ষা" এর সংকীর্ণ দৃষ্টিভঙ্গিতে এমন কাজ করা হয় যা মানুষকে আরও বেশি সুরক্ষিত কাজের ক্ষেত্র নিয়ে আসে up
ক্রেগ রিঞ্জার

10

সম্ভবত subprocess.list2cmdlineএকটি ভাল শট হয়?


দেখতে বেশ সুন্দর লাগছে। এটা আকর্ষণীয় (ইন নথিভুক্ত করা না ... docs.python.org/library/subprocess.html অন্তত)
টম

4
এটি যথাযথভাবে পালাতে পারে না subprocess.list2cmdline(["'",'',"\\",'"'])gives দেয়' "" \ \"
টিনো

এটি শেল প্রসারণ প্রতীকগুলি
এড়ায়

সাবপ্রসেস.লিস্ট 2 সেমিডলাইন () কি কেবল উইন্ডোজের জন্য উদ্দিষ্ট?
জেএস।

@ জেএস হ্যাঁ, list2cmdlineউইন্ডোজ সেমিডি.এক্সি সিনট্যাক্স অনুসারে ( পাইথন সোর্স কোডে ফাংশন ডকস্ট্রিং দেখুন )। shlex.quoteইউনিক্স বোর্ন শেল সিনট্যাক্সের সাথে সঙ্গতিপূর্ণ, তবে এটি সাধারণত প্রয়োজন হয় না কারণ ইউনিক্সের সরাসরি আর্গুমেন্টগুলি পাস করার জন্য ভাল সমর্থন রয়েছে। উইন্ডোজের পক্ষে আপনার সমস্ত যুক্তি (আপনি সঠিকভাবে পালানোর প্রয়োজনীয়তা) সহ একটি স্ট্রিং পাস করার প্রয়োজন রয়েছে Windows
ইস্টারদা

7

নোট করুন যে পাইপস.কোটটি আসলে পাইথন 2.5 এবং পাইথন 3.1 তে ভাঙ্গা এবং ব্যবহার করা নিরাপদ নয় - এটি শূন্য দৈর্ঘ্যের আর্গুমেন্টগুলি পরিচালনা করে না।

>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1  arg3

পাইথন ইস্যু দেখুন 7476 ; এটি পাইথন ২.6 এবং ৩.২ এবং আরও নতুন স্থির করা হয়েছে।


4
পাইথনের কোন সংস্করণ আপনি ব্যবহার করছেন? সংস্করণ 2.6 সঠিক আউটপুট তৈরি করেছে বলে মনে হচ্ছে: মাইকম্যান্ড আরজি 1 '' আরজি 3 (স্ট্যাক ওভারফ্লোতে ফন্টটি বলা শক্ত করে তোলে যদিও! এটি একসাথে দুটি একক-কোট)!
ব্র্যান্ডন রোডস

4

বিজ্ঞপ্তি : এটি পাইথন ২...x এর একটি উত্তর।

উত্স অনুসারে , pipes.quote()" / bin / sh এর একক যুক্তি হিসাবে একটি স্ট্রিংকে নির্ভরযোগ্যভাবে উদ্ধৃত করা" এর একটি উপায় । (যদিও এটি ২. 2. সংস্করণ থেকে অবহেলা করা হয়েছে এবং শেষ পর্যন্ত shlex.quote()ফাংশন হিসাবে পাইথন ৩.৩ এ প্রকাশ্যে প্রকাশ করা হয়েছে ।)

উপর অন্যদিকে , subprocess.list2cmdline()একটি উপায় "হয় একটি কমান্ড লাইন স্ট্রিং মধ্যে আর্গুমেন্ট একটি ক্রম অনুবাদ, যেমন একই নিয়ম ব্যবহার মাইক্রোসফট সি রানটাইম "।

আমরা এখানে আছি, কমান্ড লাইনের জন্য স্ট্রিংগুলি উদ্ধৃত করার প্ল্যাটফর্মের স্বাধীন উপায়।

import sys
mswindows = (sys.platform == "win32")

if mswindows:
    from subprocess import list2cmdline
    quote_args = list2cmdline
else:
    # POSIX
    from pipes import quote

    def quote_args(seq):
        return ' '.join(quote(arg) for arg in seq)

ব্যবহার:

# Quote a single argument
print quote_args(['my argument'])

# Quote multiple arguments
my_args = ['This', 'is', 'my arguments']
print quote_args(my_args)

3

আমি বিশ্বাস করি যে ওএস.সিস্টেম ব্যবহারকারীর জন্য যা কিছু কমান্ড শেল কনফিগার করা আছে কেবল তার জন্যই অনুরোধ করে, তাই আপনি প্ল্যাটফর্মটি স্বাধীন উপায়ে এটি করতে পারবেন বলে আমি মনে করি না। আমার কমান্ড শেলটি ব্যাশ, ইমাস, রুবি বা ভূমিকম্প 3 থেকে যে কোনও কিছু হতে পারে। এই প্রোগ্রামগুলির মধ্যে কিছু আপনি তাদের কাছে যে ধরণের আর্গুমেন্ট পাঠাচ্ছেন তা প্রত্যাশা করে না এবং এমনকি যদি সেগুলি করেও থাকে তবে তারা তাদের পলায়ন একইভাবে করার কোনও গ্যারান্টি নেই।


2
বেশিরভাগ বা সম্পূর্ণ পসিক্স-কমপ্লায়েন্ট শেলটি আশা করা অযৌক্তিক নয় (কমপক্ষে সর্বত্র তবে উইন্ডোজের সাথে এবং আপনি জানেন যে "শেল" তবে যাইহোক)। ওএস.সিস্টেম not শেল ব্যবহার করে না, কমপক্ষে এখানে নেই।

2

আমি যে ফাংশনটি ব্যবহার করি তা হ'ল:

def quote_argument(argument):
    return '"%s"' % (
        argument
        .replace('\\', '\\\\')
        .replace('"', '\\"')
        .replace('$', '\\$')
        .replace('`', '\\`')
    )

এটি হ'ল: আমি যুক্তিটি সর্বদা ডাবল উদ্ধৃতিতে আবদ্ধ করি এবং তারপরে ডাবল উদ্ধৃতিগুলির মধ্যে বিশেষ একমাত্র অক্ষরকে ব্যাকস্ল্যাশ-কোট করি।


মনে রাখবেন যে আপনার '\\ "', '\\ $' এবং '\`' ব্যবহার করা উচিত, অন্যথায় পালানোর
ঘটনাটি

1
অতিরিক্তভাবে, কিছু (অদ্ভুত) লোকালগুলিতে ডাবল উদ্ধৃতি ব্যবহার করার ক্ষেত্রে সমস্যা রয়েছে ; প্রস্তাবিত ফিক্স ব্যবহার করে pipes.quoteযা @ জনজ্ঞানম্যান নির্দেশ করেছেন যে এটিও ভেঙে গেছে। গ্রেগ হিউগিল এর উত্তর এইভাবে ব্যবহার করা হয়। (নিয়মিত
কেসগুলির

-3

আপনি যদি সিস্টেম কমান্ডটি ব্যবহার করেন, তবে আমি চেষ্টা করব এবং হোস্টলিস্টটি যা OS.sstm () কলটিতে যায় .. উদাহরণস্বরূপ ..

clean_user_input re.sub("[^a-zA-Z]", "", user_input)
os.system("ls %s" % (clean_user_input))

সাবপ্রসেস মডিউলটি আরও ভাল বিকল্প এবং আমি যেখানেই সম্ভব ওএস.সিস্টেম / সাবপ্রসেসের মতো কিছু ব্যবহার না করার চেষ্টা করার পরামর্শ দিচ্ছি।


-3

আসল উত্তরটি: os.system()প্রথম স্থানে ব্যবহার করবেন না । subprocess.callপরিবর্তে ব্যবহার করুন এবং অনির্বাচিত আর্গুমেন্ট সরবরাহ করুন।


6
প্রশ্নটিতে একটি উদাহরণ রয়েছে যেখানে সাবপ্রসেস কেবল ব্যর্থ হয়। আপনি যদি সাবপ্রসেস ব্যবহার করতে পারেন তবে অবশ্যই আপনার উচিত। তবে আপনি যদি না পারেন ... সাবপ্রসেস সবকিছুর সমাধান নয় । ওহ, এবং আপনার উত্তর প্রশ্নের কোনও উত্তর দেয় না।
জার্জেন এ। এয়ারহার্ড

@ জর্জেনা.এরহার্ড ওপির উদাহরণটি ব্যর্থ হয় না কারণ তিনি শেল পাইপ ব্যবহার করতে চান? আপনার সর্বদা সাবপ্রসেস ব্যবহার করা উচিত কারণ এটি শেল ব্যবহার করে না। এটি একটি উদাহরণের জন্য কিছুটা আনাড়ি , তবে আপনি স্থানীয় সাবপ্রসেসিতে পাইপগুলি করতে পারেন, কয়েকটি পিপিআই প্যাকেজ রয়েছে যা এটি আরও সহজ করার চেষ্টা করে। আমি যতটা সম্ভব পাইথানটিতে আমার প্রয়োজনের পরে প্রসেসিংয়ের প্রবণতা করি, আপনি সর্বদা আপনার নিজের স্ট্রিংআইও বাফার তৈরি করতে পারেন এবং সাব-প্রোসেসিসের সাহায্যে জিনিসগুলি পুরোপুরি নিয়ন্ত্রণ করতে পারেন।
থারস্মমনার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.