bash_history: खतरनाक आदेशों पर टिप्पणी करें: `#`


16

बैश इतिहास में "खतरनाक" कमांड लॉग करने से रोकने के लिए, मैंने अपनी .bashrcफ़ाइल में निम्नलिखित पंक्ति जोड़ी है :

HISTIGNORE='rm *:mv *:cp *:cat*>*:pv*>*'

यह अच्छी तरह से काम करता है, लेकिन इसका एक साइड इफेक्ट है: मैं एक मशीन पर निष्पादित कमांड का पूरा इतिहास नहीं देख सकता। मान लीजिए कि मेरे पास प्रयोगों के लिए कई मशीनें हैं, और मैं सभी आदेशों को निष्पादित करने में सक्षम होना चाहता हूं। मैं historyमार डाला आंतरिक प्रदर्शित करने के लिए कमांड का उपयोग करेगा , और शायद आज की तारीख के लिए grep:

history | grep Sep-28

मुझे जो करना है वह "खतरनाक" कमांड को भी लॉग इन करना होगा, लेकिन #लाइन की शुरुआत में डाल दें , ताकि अगर मैं गलती से कमांड को इतिहास से निष्पादित करने के लिए होता हूं, तो कोई नुकसान नहीं होगा।

मुझे पता नहीं है कि क्या यह संभव है।

अद्यतन और स्पष्टीकरण:

मेरे लिए एक समस्या यह है कि मुख्य कारण यह है कि मैं आमतौर पर कई टर्मिनलों से अपनी मशीन से जुड़ा हुआ हूं, और एक टर्मिनल पर निष्पादित किसी भी कमांड को तुरंत अन्य टर्मिनलों के इतिहास में पढ़ा जाता है। इससे हासिल होता है

PROMPT_COMMAND="history -a; history -c; history -r"

आइए कल्पना करें कि मेरे पास दो टर्मिनल खुले हैं। एक में मुझे कुछ cat /dev/foo > file.outप्रक्रिया चल रही है। दूसरे में, मैं प्रगति की जांच करता हूं ls -lAhF। मैं lsदबाकर दोहराता रहता हूं ( Upऔर ENTERयह इतिहास से अंतिम आदेश है)। जैसे ही पहली कमांड खत्म होती है, इतिहास से अंतिम कमांड अब नहीं है ls, लेकिन cat /dev/foo > file.out। अगर मैं सावधान नहीं हूं, तो मैं फिर से बिल्ली शुरू कर दूंगा और file.out को अधिलेखित कर दूंगा।

मैं जो हासिल करना चाहूंगा वह यह है कि बिल्ली कमान के साथ पूर्ववर्ती होगी #, ताकि इसे निष्पादित नहीं किया जाएगा। हालाँकि, मैं अभी भी इसे इतिहास में देखता हूँ और इसे अन-कमेंट करके इसे फिर से (यदि यह एक लंबी आज्ञा है) पुनः प्रयोग कर सकता है।


अपने आदेश को मैन्युअल रूप से दोहराने के बजाय, आप उपयोग कर सकते हैं watch ls -lAhFया while sleep 1; do ls -lAhf; done; फ़ाइल का आकार देखने के बजाय, आप pv /dev/foo > file.out( ivarch.com/programs/pv.shtml ) का उपयोग कर सकते हैं ।
डेल्टब

जवाबों:


9

आप कुछ ऐसा कर सकते हैं:

fixhist() {
   local cmd histnum
   cmd=$(HISTTIMEFORMAT=/ history 1)
   histnum=$((${cmd%%[*/]*}))
   cmd=${cmd#*/} # remove the histnum
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -s "#$cmd"    # add back with a #
   esac
}
PROMPT_COMMAND=fixhist

यह विचार कि प्रत्येक प्रांप्ट से पहले, हम अंतिम इतिहास प्रविष्टि ( history 1) की जांच करते हैं और यदि यह खतरनाक में से एक है, तो हम इसे हटा देते हैं ( history -d) और इसे एक #साथ वापस जोड़ते हैं history -s

(जाहिर है, आपको अपनी HISTIGNOREसेटिंग हटाने की आवश्यकता है )।

हालांकि इसका एक अवांछित दुष्प्रभाव यह है कि यह उन लोगों के इतिहास के समय को बदल देता है rm, mv... कमांड।

इसे ठीक करने के लिए, एक विकल्प हो सकता है:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%[<*]*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       HISTFILE=/dev/stdin history -r <<EOF
#$time
#$cmd
EOF
   esac
}
PROMPT_COMMAND=fixhist

इस बार, हम पिछले इतिहास के समय को रिकॉर्ड करते हैं, और इतिहास की रेखा को वापस जोड़ने के लिए, हम history -rएक अस्थायी फ़ाइल (यहां दस्तावेज़) से उपयोग करते हैं जिसमें टाइमस्टैम्प शामिल है।

आप fixhistअपने से पहले प्रदर्शन किया जाना चाहते हैं history -a; history -c; history -r। दुर्भाग्य से, वर्तमान संस्करण bashमें एक बग है जो history -aउस अतिरिक्त पंक्ति को नहीं बचाता है जिसे हमने जोड़ा है। एक काम के बजाय इसे लिखने के लिए है:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%[<*]*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -a
       [ -f "$HISTFILE" ] && printf '#%s\n' "$time" "$cmd" >> "$HISTFILE";;
     (*)
       history -a
   esac
   history -c
   history -r
}
PROMPT_COMMAND=fixhist

यह टिप्पणी करने वाले कमांड को यह करने के बजाय खुद हिस्टीमर में जोड़ना history -aहै।


क्या आप कृपया बता सकते हैं कि क्या cmd=${cmd#*[0-9] }करता है? और जहां वास्तव में मैं रखना चाहिए fixhistमेरी में PROMPT_COMMAND? फिलहाल, इसमें पहले से ही शामिल हैPROMPT_COMMAND="history -a; history -c; history -r"
मार्टिन वेज्टर

क्या की भूमिका है HISTTIMEFORMAT=/? मैंने पहले ही सेट कर लिया है export HISTTIMEFORMAT="%b-%d %H:%M "। वैसे, जब मैं आपके कोड को अपने में जोड़ता हूं $HOME/.bashrc, तो कुछ नहीं होता है।
मार्टिन वेगाटर

HISTTIMEFORMAT=/केवल उस एक मंगलाचरण के historyलिए एक आउटपुट प्राप्त करना है जैसे 123 /rm xकि cmd निकालना आसान है। कुछ संस्करणों के साथ एक मुद्दा था bashजहां $HISTCMDउस संदर्भ में फर्जी था, नए संस्करण का प्रयास करें।
स्टीफन चेजालस

अभी भी काम नहीं करता है। मैं सोच रहा हूँ, क्या #कोड में टिप्पणी के रूप में कार्य नहीं करते हैं .bashrc?
मार्टिन वेग्टर

1
@MartinVegter, हाँ, संशोधित इतिहास प्रविष्टियों के लिए, इतिहास संख्या के बाद bashआवेषण *जो अपेक्षित नहीं था। अब तय होना चाहिए।
स्टीफन चेजलस

11

मैं आपके प्रश्न का ठीक-ठीक उत्तर नहीं देने जा रहा हूं, लेकिन हो सकता है कि आप अपनी समस्या का एक वैकल्पिक समाधान दें।

यदि मैं सही ढंग से समझता हूं कि आप उन गलतियों के बारे में चिंतित हैं जो आप टाइप करके कर सकते हैं, उदाहरण के लिए, !rmयदि ऐसा हुआ कि rmइतिहास में पिछली कमांड कुछ ऐसा हटाती है जिसे आप रखना चाहते हैं।

इस मामले में, एक अच्छा बैश विकल्प है histverify। यदि आप shopt -s histverify, और यदि आप बैंग के साथ एक कमांड को याद करते हैं !, तो यह तुरंत निष्पादित नहीं करेगा, लेकिन रीडलाइन में लोड किया जाएगा ताकि आप या तो इसे निष्पादित करने का निर्णय ले सकें या नहीं, और यह आपको इसे संपादित करने की संभावना भी देता है।

कोशिश करो:

  • इसके बिना histverify:

    $ touch some_foo
    $ rm some_foo
    $ touch some_foo
    $ !rm
    rm some_foo
    $ # oooops in fact I'd've like to keep it this time
  • के साथ histverify:

    $ shopt -s histverify
    $ touch some_foo
    $ rm some_foo
    $ touch some_foo
    $ !rm
    $ rm some_foo <cursor here>

    इस स्थिति में आपके पास पंक्ति के अंत में कर्सर होगा, इसे फिर से लॉन्च करने के लिए तैयार - या नहीं - या इसे संपादित करने के लिए।

यदि आप इस विकल्प को पसंद करते हैं, तो इसे अपने में डालें .bashrc:

shopt -s histverify
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.