এটি কীভাবে চালিত হয়েছিল তা বাশ স্ক্রিপ্ট কীভাবে বলতে পারে?


10

আমার একটি বাশ স্ক্রিপ্ট রয়েছে যা আমি চেষ্টা করছিলাম যাতে ছোট পরিবর্তনগুলির দ্বারা একটি জটিল জটিল কমান্ড চালাতে সাহায্য করে যা এটি আমাকে ইকো এবং পড়ার মাধ্যমে জিজ্ঞাসা করতে পারে।

কমান্ডটি কার্যকর করতে টার্মিনাল চালাতে বাধ্য করার সমাধান আমি পেয়েছি, তবে আমি এতে আগ্রহী নই। আমি যা করতে চাই তা হ'ল, যদি আমি স্থানটি সরিয়ে রাখি এবং এটিতে নটিলাসে এন্টার টিপুন (এটি রান সফটওয়্যার দিয়ে চালানো), এটি কেবল একটি নোটিফিকেশন পপ আপ করবে যে "দয়া করে এটি একটি টার্মিনাল থেকে চালান" saying

আমি পপআপটি ঘটতে পারি - যেমন আমি কমান্ডটি জানি - তবে বাশ স্ক্রিপ্টটি এটি টার্মিনালের অভ্যন্তরে চালিত হচ্ছে কিনা তা জানাতে পারব না, মনে হয় এটি সর্বদাই মনে করে। এটা কি সম্ভব?

উত্তর:


10

শর্তসাপেক্ষে প্রকাশেরman bash অধীনে থেকে :

-t fd  
    True if file descriptor fd is open and refers to a terminal.

ধরে নেওয়া fd 1 স্ট্যান্ডার্ড আউট, if [ -t 1 ]; thenআপনার জন্য কাজ করা উচিত। উন্নত শেল স্ক্রিপ্টিং গাইড দাবি যে -tএই ভাবে ব্যবহৃত উপর ব্যর্থ হবে ssh, এবং পরীক্ষা যে (stdin ব্যবহার করে, stdout- এ নয়) তাই হওয়া উচিত:

if [[ -t 0 || -p /dev/stdin ]]

-pকোনও ফাইল বিদ্যমান এবং নামযুক্ত পাইপ কিনা তা পরীক্ষা করে। তবে , আমি experientially নোট চাই এই আমার জন্য সত্য নয়: -p /dev/stdinযেহেতু উভয় স্বাভাবিক টার্মিনাল এবং SSH সেশন ব্যর্থ if [ -t 0 ](অথবা -t 1) উভয় ক্ষেত্রেই কাজ করে (যে অধ্যায় এ বিষয় সম্পর্কে নিচে গিলেজ মন্তব্য দেখতে অ্যাডভান্সড শেল স্ক্রিপ্টিং গাইড )।


প্রাথমিক সমস্যাটি যদি এমন কোনও বিশেষ প্রসঙ্গ হয় যেখান থেকে আপনি সেই প্রসঙ্গে উপযুক্তভাবে আচরণের জন্য স্ক্রিপ্টটি কল করতে চান, আপনি এই সমস্ত প্রযুক্তিগত দিকটি ছাড়িয়ে নিতে পারেন এবং একটি মোড়ক এবং একটি কাস্টম ভেরিয়েবল ব্যবহার করে নিজের স্বর কিছুটা বাঁচাতে পারেন:

!#/bin/bash

export SPECIAL_CONTEXT=1
/path/to/real/script.sh

এটি live_script.shবা যাই হোক না কেন কল করুন এবং তার পরিবর্তে ডাবল ক্লিক করুন। আপনি অবশ্যই কমান্ড লাইন আর্গুমেন্টের সাহায্যে একই জিনিসটি সম্পাদন করতে পারেন তবে জিইউআই ফাইল ব্রাউজারের কাজের জন্য পয়েন্ট তৈরি করতে এবং ক্লিক করতে একটি মোড়কের প্রয়োজন হবে।


5
এটি সঠিক উত্তর - এটি পসিএক্স কীভাবে বলে যে কোনও শেলটি ইন্টারেক্টিভ কিনা তা সনাক্ত করা উচিত।
মাইকজার্ভ

2
@ ড্যানিয়েলআমায়া - আপনি যদি ইনপুট পুনর্নির্দেশ করেন তবে স্ক্রিপ্টটি টার্মিনালে চালিত হচ্ছে না। স্ক্রিপ্টটি কোনও টার্মিনালে চলছে কিনা তা কীভাবে সনাক্ত করা যায় তা প্রশ্ন।
মাইকসার্ভ

2
আপনি কি এর ||মধ্যে [ … ]যেমন ব্যবহারের বিষয়ে নিশ্চিত ? আপনি যদি ব্যবহার করেন [[ … ]]তবে এটি ঠিক থাকবে তবে সাধারণত ||কমান্ডগুলি পৃথক করতে ব্যবহৃত হয় এবং এটির [ -t 0একটি ভুল অনুরোধ [কারণ এর শেষটি ]অনুপস্থিত। সাধারণত কোন আদেশ -pহয় না। আমি টার্মিনালের জন্য পরীক্ষার সাথে একমত; এটি সম্ভবত এটি করার উপায়। এটি কেবল সিনট্যাক্স যা আমি উদ্বিগ্ন।
জোনাথন লেফলার

1
পুনঃটুইট এটি একটি সিনট্যাক্স ত্রুটি তৈরি করতে পারে, যেহেতু শেল অপারেটরটি ||প্রয়োজনীয় চূড়ান্ত ]যুক্তির আগে দেখা যায় [
চ্যানার

3
অ্যাডভান্সড ব্যাশ-স্ক্রিপ্টিং গাইড থেকে এই বিভাগে বেশ কয়েকটি ত্রুটি রয়েছে। PS1শেলটি ইন্টারেক্টিভ কিনা তা জানার জন্য একটি নির্ভরযোগ্য পরীক্ষা নয়। "যদি কোনও স্ক্রিপ্টটি এটি ইন্টারেক্টিভ শেলের মধ্যে চলছে কিনা তা পরীক্ষা করা দরকার" এটিও বিভ্রান্তিকর: এটি এমন হওয়া উচিত যা কিছু কোড পরীক্ষা করার প্রয়োজন হয় - কোনও স্ক্রিপ্ট সাধারণত ইন্টারেক্টিভ শেলের মধ্যে চলতে থাকে না (তবে এটি হতে পারে, যদি এটি উত্সাহিত হয়) । জন্য টেস্টিং iমধ্যে $-পরীক্ষা করার সঠিক উপায় যদি শেল ইন্টারেক্টিভ হয়। স্ক্রিপ্টটি কোনও টার্মিনালে চলমান কিনা তা পরীক্ষা করার জন্য -t 0বা -t 2সঠিক উপায়, যা ইন্টারেক্টিভ হওয়ার চেয়ে পৃথক।
গিলস

0

শেল নেস্টিংয়ের স্তর সনাক্ত করতে ব্যাশ $ SHLVL পরিবর্তনশীলটি ব্যবহার করুন vari ডাবল ক্লিক করে 'কাঁচা' চালিত স্ক্রিপ্টে এটি 1 হবে, টার্মিনালের মধ্যে চলমান স্ক্রিপ্টে এটি 2 হবে।

#!/bin/bash
if (( SHLVL < 2 )) ; then
    echo "Please run this from a terminal."
    read -p "Press <Enter> to close this window"
    exit 1
fi
# rest of script

0

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

আমি কীভাবে আমার সমস্যাটি সমাধান করেছি তা এখানে:

#!/bin/bash
isxclient=$( readlink /dev/fd/2 | grep -q 'tty' && [[ -n $DISPLAY ]] ; echo $? )
if [[ ! -t 2  || $isxclient == "0" ]]; then
        notify-send "Script wasn't started from an interactive shell"
else
        echo "Script was started from an interactive shell"
fi

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


-2

আরেকটি, ব্যাশ বিকল্পগুলি ব্যবহার করে অভ্যন্তরীণ ভেরিয়েবল সেট করে $-

থেকে .bashrc,

# If not running interactively, don't do anything
case $- in
    *i*) ;;
    *) return;;
esac

একটি ইন্টারেক্টিভ শেল অগত্যা টার্মিনালের সাথে যুক্ত নয়। যখন সংযোগ দিয়ে শুরু এক স্বয়ংক্রিয়ভাবে ইন্টারেক্টিভ শুরু হয়, এই সম্ভব: cmd | sh -i | cmd
মাইকজার্ভ

এই কোডটি একটি স্ক্রিপ্টে কার্যকর করা হচ্ছে। এটি ইন্টারেক্টিভ হবে না, এমনকি যদি এটি টার্মিনালে চলমান।
গিলস 'অশুভ হওয়া বন্ধ করুন'
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.