একটি প্রক্রিয়া স্টিডিন লিখছেন


10

আমি নিম্নলিখিতটি টাইপ করি কিনা যতদূর আমি বুঝতে পারি ...

 python -i

... পাইথন-দোভাষী এখন স্টিডিনের কাছ থেকে পড়বেন, এরকম আচরণ করবেন (স্পষ্টতই):

 >>> print "Hello"
 Hello

আমি যদি এটি করি তবে এটি একই জিনিসটি করবে বলে আমি আশা করব:

 echo 'print "Hello"' > /proc/$(pidof python)/fd/0

তবে এটি আউটপুট (একটি আসল ফাঁকা লাইনের মৌমাছি করা):

 >>> print "Hello"
 <empyline>

এটি আমার কাছে দেখে মনে হচ্ছে এটি কেবল এটি নিয়েছিল print "Hello"\nএবং এতে লিখেছিল stdout, তবুও এটি ব্যাখ্যা করে নি। এটি কেন কাজ করছে না এবং এটিকে কাজ করার জন্য আমাকে কী করতে হবে?


TIOCSTI ioctl একটি টার্মিনাল এর লিখতে পারেন stdin যেন ডেটা কীবোর্ড থেকে প্রবেশ করা হয়েছে। উদাহরণস্বরূপ github.com/thrig/scriptts/blob/master/tty/
ত্তি

উত্তর:


9

শেল / দোভাষীদের এভাবে ইনপুট পাঠানো খুব সমস্যা-ঝুঁকির এবং কোনও নির্ভরযোগ্য উপায়ে কাজ করা খুব কঠিন।

সঠিক উপায় হ'ল সকেটগুলি ব্যবহার করা, এ কারণেই সেগুলি আবিষ্কার করা হয়েছিল, আপনি কমান্ড লাইনে এটি ব্যবহার করতে ncat ncবা socatএকটি সাধারণ সকেটে অজগর প্রক্রিয়াটি আবদ্ধ করতে পারেন । অথবা একটি সাধারণ অজগর অ্যাপ্লিকেশন লিখুন যা বন্দরে আবদ্ধ হয় এবং সকেটে ব্যাখ্যা করার জন্য আদেশগুলি শোনায়।

সকেট স্থানীয় হতে পারে এবং কোনও ওয়েব ইন্টারফেসের সংস্পর্শে আসে না।


সমস্যাটি হ'ল আপনি যদি pythonকমান্ড লাইন থেকে শুরু করেন তবে এটি সাধারণত আপনার শেলের সাথে সংযুক্ত থাকে যা টার্মিনালের সাথে সংযুক্ত থাকে, বাস্তবে আমরা দেখতে পারি

$ ls -al /proc/PID/fd
lrwxrwxrwx 1 USER GROUP 0 Aug 1 00:00 0 -> /dev/pty1

সুতরাং যখন আপনি stdinঅজগর সম্পর্কে লিখেন, আপনি আসলে ptyপিচিউডো-টার্মিনালে লিখছেন যা কোনও কার্নেল ডিভাইস, কোনও সাধারণ ফাইল নয়। এটি ব্যবহার করে ioctlনা readএবং writeতাই আপনি আপনার স্ক্রিনে আউটপুট দেখতে পাবেন তবে এটি তৈরি প্রক্রিয়াতে প্রেরণ করা হবে না ( python)

আপনি যা চেষ্টা করছেন তার অনুলিপি করার একটি উপায় হ'ল একটি fifoবা এর সাথে named pipe

# make pipe
$ mkfifo python_i.pipe
# start python interactive with pipe input
# Will print to pty output unless redirected
$ python -i < python_i.pipe &
# keep pipe open 
$ sleep infinity > python_i.pipe &
# interact with the interpreter
$ echo "print \"hello\"" >> python_i.pipe

আপনি screenকেবল ইনপুট জন্য ব্যবহার করতে পারেন

# start screen 
$ screen -dmS python python
# send command to input
$ screen -S python -X 'print \"hello\"'
# view output
$ screen -S python -x

আপনি যদি পাইপটি খোলা রাখেন (উদাহরণস্বরূপ sleep 300 > python_i.pipe &) অন্য দিকটি বন্ধ হবে না এবং pythonপাইপের নিচে কমান্ডগুলি গ্রহণ করতে থাকবে। এর মাধ্যমে প্রেরিত কোনও ইওএফ নেই echo
রোয়াইমা

@ রাইমা তুমি ঠিকই বলেছো, আমার বোঝার মধ্যে আমি ভুল হয়ে গিয়েছিলাম যে প্রবাহ বন্ধ হয়ে গেলে প্রতিধ্বনি ইওএফ প্রেরণ করে। এটি |পাইপের সাহায্যে এড়ানো যায় না , তবে কি সঠিক?
ক্র্যাসিক

আমি ইতিমধ্যে ফিফো রাস্তায় ছিলাম, তবে এটির একটি ইওএফ পাওয়ার echo something > fifoকারণ এটি অনেক অ্যাপ্লিকেশন বন্ধ করে দেবে। sleep infinity > fifoকার্যসংক্রান্ত যদিও আমার মাঝামাঝি ক্রস করা হয়নি, আপনাকে ধন্যবাদ!
শেপি

1
আসলে আপনার ধারণাকে অব্যাহত রেখে, আপনি এটিও করতে পারেন python -i <> fifoযা
ইওএফ

10

প্রসেস পিআইডি 0 র ফাইল বিবরণকারী অ্যাক্সেস করা যায় না , এটি পিআইডি ফাইল ডেস্ক্রিপ্টার 0 এ খোলে এমন ফাইলটি অ্যাক্সেস করে This এটি একটি সূক্ষ্ম পার্থক্য, তবে এটি গুরুত্বপূর্ণ। একটি ফাইল বর্ণনাকারী একটি সংযোগ যা কোনও প্রক্রিয়া কোনও ফাইলের সাথে থাকে। ফাইলের বিবরণকারীকে লিখন ফাইলটি কীভাবে খোলা হয়েছে তা নির্বিশেষে ফাইলটিতে লেখেন।/proc/PID/fd/0

যদি নিয়মিত ফাইল হয় তবে এটিকে লেখার ফলে ফাইলটি পরিবর্তিত হয়। প্রক্রিয়াটি পরবর্তী কী পড়বে তা ডেটা অগত্যা নয়: এটি ফাইল বিবরণীর সাথে সংযুক্ত অবস্থানের উপর নির্ভর করে যা প্রক্রিয়াটি ফাইলটি পড়তে ব্যবহার করছে। যখন একটি প্রক্রিয়া খোলা হয় , এটি অন্যান্য প্রক্রিয়ার মতো একই ফাইল পায় তবে ফাইলের অবস্থানগুলি স্বাধীন।/proc/PID/fd/0/proc/PID/fd/0

যদি কোনও পাইপ হয় তবে তারপরে এটি লিখনের বাফারের সাথে ডেটা যুক্ত করে। সেক্ষেত্রে পাইপ থেকে যে প্রক্রিয়াটি পড়ছে তা ডেটা পড়বে।/proc/PID/fd/0

যদি একটি টার্মিনাল হয়, তারপরে এটি লিখে টার্মিনালের ডেটা আউটপুট করে। একটি টার্মিনাল ফাইল দ্বি নির্দেশমূলক: এটিতে লেখার ফলে ডেটা আউটপুট হয়, অর্থাৎ টার্মিনালটি পাঠ্য প্রদর্শন করে; টার্মিনাল থেকে পড়া তথ্য উপাত্ত ইনপুট করে, অর্থাত্ টার্মিনালটি ব্যবহারকারী ইনপুট প্রেরণ করে।/proc/PID/fd/0

পাইথন টার্মিনালে পড়া এবং লেখার জন্য উভয়ই। আপনি যখন চালান echo 'print "Hello"' > /proc/$(pidof python)/fd/0, আপনি print "Hello"টার্মিনাল লিখছেন । টার্মিনালটি print "Hello"নির্দেশ অনুযায়ী প্রদর্শিত হবে । পাইথন প্রক্রিয়াটি কিছুই দেখতে পায় না, এটি এখনও ইনপুটটির জন্য অপেক্ষা করছে।

আপনি যদি পাইথন প্রক্রিয়াতে ইনপুট খাওয়াতে চান তবে এটি করার জন্য আপনাকে টার্মিনালটি পেতে হবে। এটি করার উপায়গুলির জন্য ক্র্যাসিকের উত্তর দেখুন ।


2

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

লিনাক্সে আইওসিটিএল অনুরোধের মাধ্যমে ইউজার ইনপুটকে সিমুলেট করার একটি নন-পিক্সিক উপায় রয়েছে TIOCSTI(টার্মিনাল আই / ও কন্ট্রোল - সিমুলেট টার্মিনাল ইনপুট) যা আমাদের কোনও টার্মিনালে অক্ষর প্রেরণ করতে দেয় যেমন কোনও ব্যবহারকারী দ্বারা টাইপ করা হয়েছিল।

আমি কীভাবে এটি কাজ করে তা সম্পর্কে মাত্রাতিরিক্ত সচেতন, কিন্তু এই উত্তরের উপর ভিত্তি করে , এটির লাইন বরাবর কিছু দিয়ে এটি করা সম্ভব হবে

import fcntl, sys, termios

tty_path = sys.argv[1]

with open(tty_path, 'wb') as tty_fd:
    for line in sys.stdin.buffer:
        for byte in line:
            fcntl.ioctl(tty_fd, termios.TIOCSTI, bytes([byte]))

কিছু বাহ্যিক সংস্থান:

http://man7.org/linux/man-pages/man2/ioctl.2.html

http://man7.org/linux/man-pages/man2/ioctl_tty.2.html


লক্ষ্য করুন যে প্রশ্নটি কোনও নির্দিষ্ট অপারেটিং সিস্টেমের সাথে সুনির্দিষ্ট নয়, এবং টিআইওসিএসটিআই লিনাক্স দ্বারা উদ্ভূত হয়নি। এই উত্তরটি লেখার প্রায় দু'বছর আগে, সুরক্ষার কারণে লোকেরা TIOCSTI ছাড়তে শুরু করে। unix.stackexchange.com/q/406690/5132
জেডিবিপি

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