सिस्टम में लॉगिन करने पर स्वचालित रूप से vi मोड पर बैश रीडलाइन कैसे सेट करें?


9

मेरी टीम हज़ारों लिनक्स / यूनिक्स मशीनों के लिए ज़िम्मेदार है, इसलिए स्वाभाविक रूप से रूट खाता प्रवेशकों के बीच "साझा" है। मैं vi मोड पसंद करता हूं, अन्य लोग emacs मोड पसंद करते हैं।

मैं किसी भी मशीन पर SSH लॉगिन करने पर bash की रीडलाइन को vi मोड में कैसे सेट कर सकता हूं, बिना vi मोड का उपयोग करने के लिए हर किसी को मजबूर किए बिना?

संक्षेप में, set -o viलॉगिन के बाद का प्रभाव वास्तव में इसे हर बार टाइप करने के बिना, और इसे हर किसी पर मजबूर किए बिना करना होगा (जितना emacs मोड मुझे परेशान कर रहा है, vi मोड उन्हें परेशान कर रहा है)।

मुझे पता है कि यह एक समस्या नहीं होगी यदि हर कोई अपने स्वयं के खातों का उपयोग सुदो के साथ विशेषाधिकार प्राप्त आदेशों को निष्पादित करने के लिए करेगा, लेकिन मेरे नियंत्रण से बाहर की परिस्थितियों के कारण यह दुख की बात नहीं है।


1
यह आसान नहीं है। एक तरीका sshd की लॉग फ़ाइल को पार्स करने का है और यह देखने के लिए कि किस कुंजी का उपयोग लॉग-इन करने के लिए किया गया था। मैं क्लाइंट-साइड समाधान की उम्मीद कर रहा था, उदाहरण के लिए रिमोट साइड पर मेरा स्थानीय रीडलाइन कॉन्फ़िगर करने का तरीका या ऐसा कुछ, या कुछ डार्क ओपनएसएसएच जादू जो set -o viमुझे शेल के नियंत्रण देने से पहले चुपचाप निष्पादित करता है ।
पैट्रिक

1
हो सकता है कि आप सर्वर में ssh के क्लाइंट पर एक एक्सपेक्ट स्क्रिप्ट का उपयोग कर सकते हैं, set -o viकमांड भेज सकते हैं , फिर इंटरेक्टिव मोड में स्विच कर सकते हैं।
बरमार

1
कम से कम ओपनएसएसएच sshdकई पर्यावरण चर स्थापित करता है जो आपको यह निर्धारित करने में मदद कर सकते हैं कि दूसरे छोर पर कौन है। उदाहरण के लिए, SSH_CLIENTकनेक्टिंग आईपी-एड्रेस (और साथ ही क्लाइंट का आउटगोइंग / इनकमिंग पोर्ट) शामिल है। इस के साथ ~/.bashrcआप शायद सिर्फ तुम्हारे लिए काम करने की अनुमति देता है ।
सामी लाईन

1
इनाम कहते हैं कि आप "ग्राहक पक्ष समाधान" की तलाश कर रहे हैं - वह क्या है? एक यूनिक्स मेजबान पर ssh? पोटीन? हमिंगबर्ड? जावा एसएसएच? Cygwin?
जेफ स्कालर

1
आप हजारों मशीनों का जिक्र करते हैं। क्या आप एक मशीन से शुरू करना चाहते हैं और इन मशीनों को प्राप्त करना चाहते हैं, या क्या आप मशीन से मशीन से मशीन को वीआई मोड पर ले जाना चाहते हैं?
इकारस

जवाबों:


3

यह करने का एक मूर्खतापूर्ण तरीका है, जो वास्तव में केवल सार्वजनिक-कुंजी प्रमाणीकरण के साथ अच्छा काम करता है:

सबसे पहले, सुनिश्चित करें कि आपकी स्थानीय मशीन उस ncपर है।

दूसरा, अभी भी आपकी स्थानीय मशीन पर, एक स्क्रिप्ट बनाएं (मैं इसे कॉल करूंगा connect-to-server) और इसे उस जगह पर ${PATH}रखूं जहां आपके बारे में पता हो: *

#!/bin/sh
# connect-to-server
ssh -q server-hostname "touch .yourname" </dev/null >/dev/null 2>&1
nc server-hostname 22

अगला, .bashrcकहीं न कहीं शामिल करने के लिए दूरस्थ प्रणाली को संशोधित करें :

# partial .bashrc
if [ -f "${HOME}/.yourname" ]; then
  rm "${HOME}/.yourname"
  set -o vi
fi

अंत में, अपनी स्थानीय मशीन में वापस, ~/.ssh/configजोड़ने के लिए संपादित करें :

# partial ssh config
Host serverNickname
  Hostname server-hostname
  ProxyCommand connect-to-server

इस दृष्टिकोण के डाउनसाइड्स (और मैं इसे मूर्खतापूर्ण क्यों कहता हूं):

  • यदि कोई वास्तविक प्रॉक्सी कमांड की आवश्यकता है, तो यह अधिक जटिल हो जाता है।
  • यदि कोई अन्य व्यक्ति उसी समय में लॉग इन करता है, तो एक मौका है कि .yournameफ़ाइल को अभी तक हटाया नहीं गया है, जिस स्थिति में वे भी मिलते हैं set -o vi
  • सबसे महत्वपूर्ण बात, यदि आप करते हैं ssh serverNickname command, तो commandचलेगा, लेकिन (क्योंकि .bashrcकभी खट्टा नहीं होता है) .yournameफ़ाइल बनी रहती है, इसलिए यह आपके ssh config में दूसरा उपनाम होने के लिए विनम्र होगा जो छद्म प्रॉक्सी का उपयोग नहीं करता है।

वास्तव में, इस दृष्टिकोण का एकमात्र उल्टा यह है कि आपके sshआदेश को कोई अतिरिक्त तर्क देने की आवश्यकता नहीं है।


* यदि आप रिमोट सिस्टम पर कुछ भी बदलना नहीं चाहते हैं, तो यहां एक वैकल्पिक छद्म प्रॉक्सी है जो एक अस्थायी बनाता है .bashrc:

#!/bin/sh
# connect-to-server
ssh -q server-hostname 'ln .bashrc .bashrc.real; cat .bashrc.real <(printf "set -o vi; ln -f .bashrc.real .bashrc\n") >.bashrc.yourname; ln -f .bashrc.yourname .bashrc' </dev/null >/dev/null 2>&1
nc server-hostname 22

यह अन्य विधि के सभी समान नुकसान है, इसलिए आप अभी भी अपने sshकॉन्फ़िगरेशन में एक दूसरा उपनाम चाहते हैं जो छद्म प्रॉक्सी को आमंत्रित नहीं करता है।


बहुत रचनात्मक। सुझाव के लिए धन्यवाद। मैं पहले से ही ProxyCommand का उपयोग बड़े पैमाने पर करता हूं (कुछ नेटवर्क / मेजबानों को पहुंचने के लिए 5+ हॉप्स की आवश्यकता होती है) और यह जल्दी से एक कॉन्फ़िगरेशन दुःस्वप्न का परिणाम देगा। संपादित करें: सभी उत्तरों को देखते हुए मुझे लगता है कि आपका सबसे करीब आता है।
पैट्रिक

4

मैं इसके लिए जाऊंगा:

ssh server -t "bash --login -o vi"

लेकिन यह आप एक व्यवस्थापक हैं, आप कुछ क्लीनर की कोशिश कर सकते हैं। उदाहरण के लिए, आप SendEnvकिसी विशिष्ट चर को प्रसारित करने के लिए क्लाइंट साइड पर ssh विकल्प का उपयोग कर सकते हैं , इसे स्वीकार करने के AcceptEnvलिए sshdकॉन्फ़िगरेशन (सर्वर साइड) में उपयोग करें और इसके आधार पर, .bashrcचर के मान के अनुसार व्यवहार को समायोजित करने के लिए रूट की फाइल को संशोधित करें ।

इसका तात्पर्य sshdसभी मेजबानों के साथ-साथ उनके पर भी विन्यास बदलने से है .bashrc। हालांकि, "स्टैंडअलोन" करने का तरीका बिल्कुल नहीं ...


3

एक आसान ग्राहक पक्ष समाधान के लिए:

alias connect='ssh -t root@server "bash -o vi"'

यह विफल हो जाएगा यदि रूट का शेल आरंभीकरण स्क्रिप्ट स्पष्ट रूप से उपयोग करता है set -o emacsया सेट करता EDITORहै emacs, या यदि रूट की .initrcफ़ाइल emacsकुंजी बाइंडिंग को आमंत्रित करती है ।

इस जवाब के बाकी सर्वर-साइड समाधान की चिंता करते हैं।


यह तब काम करता है जब आप sshमशीन में होते हैं और फिर उपयोग करते हैं sudo -i:

आपके लिए /root/.bashrc:

if [[ -n "$SUDO_USER" ]] && [[ -f /root/.bashrc-"$SUDO_USER" ]]; then
  source /root/.bashrc-"$SUDO_USER"
fi

यह आपको एक व्यक्तिगत bashrcफाइल रखने की अनुमति देता है, /root/.bashrc-patrickजिसमें आप जो चाहें, जैसे चाहें कर सकते हैं set -o vi

इस पर निर्भर करते हुए उस आरसी फ़ाइल को लेने के लिए एक कुछ अनुभवहीन दृष्टिकोण के साथ संयोजन $SSH_CLIENT:

if [[ -n "$SUDO_USER" ]]; then
  person="$SUDO_USER"
elif [[ -n "$SSH_CLIENT" ]]; then

  case "$SSH_CLIENT" in
    192.168.216.100*)  person="joe" ;;
    192.168.216.120*)  person="patrick" ;;
    192.168.216.150*)  person="lindsey" ;;
  esac

fi

if [[ -n "$person" ]] && [[ -f /root/.bashrc-"$person" ]]; then
  source /root/.bashrc-"$person"
fi

यह स्पष्ट रूप से केवल तभी काम करता है जब आप हर समय एक ही आईपी पते से जुड़ रहे हों ...

एक अन्य दृष्टिकोण जो आपके द्वारा उपयोग किए जाने वाले विशेष SSH कुंजी के टिप्पणी क्षेत्र का उपयोग करता है, जो सर्वर पर SSH एजेंट को अग्रेषित करने पर काम करता है:

ssh_comment="$( ssh-add -L | grep -f /root/.ssh/authorized_keys | awk '{ print $NF '} | head -n 1 )"

यह उस कुंजी के लिए टिप्पणी क्षेत्र को चुनता है जिसे आप सर्वर से कनेक्ट करते थे। head -n 1मामले में है कि आप में अपनी चाबी के कई हैं तो आप authorized_keysफ़ाइल।

फिर आप $ssh_commentस्रोत के लिए सीधे एक आरसी फ़ाइल को लेने के लिए उपयोग कर सकते हैं , या तो सीधे $SUDO_USERऊपर के दृष्टिकोण के साथ (जिसमें टिप्पणी $ssh_commentकुछ सफाई से गुजरना पड़ सकता है यदि यह एक मार्गनाम है), या दृष्टिकोण के caseसाथ एक बयान के माध्यम से $SSH_CLIENT


मिलान करना SSH_CLIENTऔर SUDO_USERवह है जो मैं वर्तमान में उपयोग करता हूं, लेकिन इसके लिए सर्वर साइड संशोधन की आवश्यकता है और यह विशेष रूप से विश्वसनीय नहीं है। मैं शुद्ध क्लाइंट-साइड समाधान की उम्मीद कर रहा था। हालांकि सुझाव के लिए धन्यवाद।
पैट्रिक

3

यदि आप वास्तव में इसे सर्वर की ओर संशोधित किए बिना करना चाहते हैं, तो:

1) कुछ इस तरह चलाओ

$ ssh user@host -t 'bash -l -o vi' 

मुझे नहीं लगता कि उस पर प्रलेखन बहुत स्पष्ट है, लेकिन -o optionउल्लेख किया गया है, और काम करने लगता है।

2) उपयोग की उम्मीद:

expectस्क्रिप्ट:

$ cat bashsetup.expect
#!/usr/bin/expect -f 

set user [lindex $argv 0];
set host [lindex $argv 1];

spawn ssh -l $user $host
expect "$ "
send "set -o vi\n"
interact

इसे निष्पादन योग्य बनाएं और चलाएं:

$ ./bashsetup.expect user testhost
spawn ssh -l user testhost
[motd, blahblah...]
user@testhost ~$ set -o vi
user@testhost ~$ 

यह मानता है कि आप पासवर्ड दर्ज किए बिना (दूरस्थ होस्ट या आपकी कुंजी के लिए) लॉगिन कर सकते हैं, अन्यथा उम्मीद की स्क्रिप्ट को ध्यान में रखना होगा। लेकिन मशीनों के बहुत से आप पहले से ही होने की संभावना है। इसके अलावा, मैं उम्मीद है कि आपके शीघ्र के अनुसार डॉलर चिन्ह और एक अंतरिक्ष, संपादन के लिए: "# "शायद।

हालांकि अगर प्रॉम्प्ट से पहले छपी कुछ चीजों में वही अक्षर शामिल हैं, तो आपको अपेक्षित स्ट्रिंग में कुछ और विशिष्ट शामिल करने की आवश्यकता होगी।

इसके अलावा, वह स्क्रिप्ट अतिरिक्त तर्क देने का समर्थन नहीं करती है ssh। यदि आप चलाने के लिए एक स्पष्ट आदेश देने जा रहे हैं, तो आपको शायद vi-mode की आवश्यकता नहीं है, लेकिन यदि आपको पोर्ट टनलिंग की आवश्यकता है, तो यह एक समस्या हो सकती है।


लेकिन किसी भी मामले में, मुझे वास्तव में लगता है कि इसे अलग-अलग खातों ( sudoया सिर्फ सादे पुराने यूआईडी 0) के साथ लक्ष्य प्रणालियों पर हल किया जाना चाहिए । वैयक्तिकृत कॉन्फ़िगरेशन कई अन्य मामलों के लिए भी उपयोगी होगा, और सामान्य रूप से आपके पास कॉन्फ़िगरेशन फ़ाइल और पर्यावरण चर का एक समूह होगा जिसे आप सेट करना चाहते हैं। (विचार करें कि मान $EDITOR, vircया जो कुछ भी है , उसके मान पर सहमत नहीं हो सकते हैं ।)

इसके अलावा अलग-अलग खातों से उपयोगकर्ताओं को हटाना आसान होगा।

सभी मेजबानों पर फ़ाइलों को सिंक्रनाइज़ का कोई भी रास्ता भी तुच्छता की तरह कुछ के साथ लॉगिन करने के लिए आप की अनुमति देकर इस का समाधान होगा ssh -t user@host 'patricks_shell.sh'या ssh -t user@host 'bash --rcfile patrick.rc'


मैंने अपेक्षा का उपयोग करने के बारे में सोचा, लेकिन जैसा कि आपने पहले ही अपने प्रश्न में बताया था कि समस्या शुरू होने के संकेत के लिए कुछ अद्वितीय मिलान कर रही है interact। यह मौजूद नहीं है, संकेत अलग-अलग हो सकते हैं, जैसा कि प्रोफाइल से उद्देश्य / आउटपुट हैं। फिर भी सुझाव के लिए धन्यवाद।
पैट्रिक

1

आपके पास इस गाइड के बाद एक कस्टम आरसी फाइल हो सकती है:

उपयोगकर्ता आरसी फ़ाइल | सुरक्षित खोल: निश्चित गाइड

या आपके अधिकृत_की फ़ाइल में कमांड लाइन क्रिया इंजेक्षन करें:

SSH config auto रिमोट कमांड निष्पादित करें | यूनिक्स और लिनक्स स्टैक एक्सचेंज

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