วิธีการตั้งค่า bash readline เป็นโหมด vi โดยอัตโนมัติเมื่อเข้าสู่ระบบ?


9

ทีมของฉันรับผิดชอบเครื่อง Linux / Unix หลายพันเครื่องดังนั้นโดยปกติบัญชีรูทจะ "แชร์" ท่ามกลางผู้ดูแลระบบ ฉันชอบโหมด vi ส่วนคนอื่นชอบโหมด emacs

ฉันจะตั้งค่า readline ของ bash เป็นโหมด vi บนการล็อกอิน SSH ไปยังเครื่องใด ๆ โดยไม่บังคับให้คนอื่นใช้โหมด vi ด้วยเช่นกัน?

ในสาระสำคัญต้องการให้มีผลกระทบset -o viหลังจากเข้าสู่ระบบโดยไม่ต้องพิมพ์ทุกครั้งและไม่บังคับให้คนอื่น ๆ (เท่าที่ emacs โหมดเป็นที่น่ารำคาญสำหรับฉันโหมด vi เป็นที่น่ารำคาญสำหรับพวกเขา)

ฉันรู้ว่าสิ่งนี้จะไม่เป็นปัญหาหากทุกคนใช้บัญชีของตัวเองกับ sudo เพื่อดำเนินการคำสั่งพิเศษ แต่เนื่องจากสถานการณ์ที่อยู่นอกเหนือการควบคุมของฉันสิ่งนี้น่าเศร้าไม่ใช่ตัวเลือก


1
นั่นไม่ใช่เรื่องง่าย วิธีหนึ่งคือแยกวิเคราะห์ไฟล์บันทึกการทำงานของ sshd และดูว่ามีการใช้รหัสใดในการเข้าสู่ระบบฉันหวังว่าจะมีวิธีแก้ปัญหาฝั่งไคลเอ็นต์ตัวอย่างเช่นวิธีการส่งการกำหนดค่า readline ในพื้นที่ของฉันไปยังด้านระยะไกล เวทมนต์มืดของ OpenSSH ที่ประหารเงียบ ๆset -o viก่อนที่จะให้ฉันควบคุมกระสุน
แพทริค

1
บางทีคุณอาจใช้สคริปต์ Expect ในไคลเอนต์ที่ ssh เข้าสู่เซิร์ฟเวอร์ส่งset -o viคำสั่งจากนั้นสลับไปที่โหมดโต้ตอบ
Barmar

1
อย่างน้อย OpenSSH sshdตั้งค่าตัวแปรสภาพแวดล้อมหลายอย่างซึ่งอาจช่วยให้คุณทราบว่าใครอยู่ที่ปลายอีกด้านหนึ่ง ตัวอย่างเช่นSSH_CLIENTมีการเชื่อมต่อที่อยู่ IP (และพอร์ตขาออก / ขาเข้าของลูกค้าเช่นกัน) เล่นซอกับในเรื่องนี้~/.bashrcอาจจะช่วยให้คุณสามารถทำสิ่งเพียงสำหรับคุณ
Sami Laine

1
เงินรางวัลบอกว่าคุณกำลังมองหา "วิธีแก้ปัญหาลูกค้า" - นั่นคืออะไร? ssh บนโฮสต์ Unix หรือไม่? สีโป๊ว? Hummingbird? Java SSH Cygwin?
Jeff Schaller

1
คุณพูดถึงเครื่องจักรหลายหมื่นเครื่อง คุณต้องการที่จะเริ่มต้นจากเครื่องหนึ่งและไปที่เครื่องเหล่านี้หรือคุณต้องการที่จะกระโดดจากเครื่องหนึ่งไปอีกเครื่องหนึ่งไปยังอีกโหมดหนึ่งที่อยู่ในโหมด vi
รัส

คำตอบ:


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 ของคุณที่ไม่ได้ใช้ pseudo-proxy

ในความเป็นจริงข้อได้เปรียบเพียงอย่างเดียวของวิธีนี้คือ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การกำหนดค่าของคุณที่ไม่เรียกใช้ pseudo-proxy


สร้างสรรค์มาก ขอบคุณสำหรับคำแนะนำ ฉันใช้ ProxyCommand อย่างกว้างขวางแล้ว (บางเครือข่าย / โฮสต์ต้องการ 5+ ฮ็อพในการเข้าถึง) และสิ่งนี้จะส่งผลให้เกิดฝันร้ายการกำหนดค่าอย่างรวดเร็ว แก้ไข: ดูคำตอบทั้งหมดที่ฉันคิดว่าคุณใกล้เคียงที่สุด
Patrick

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ได้

การรวมสิ่งนี้เข้ากับวิธีการที่ค่อนข้างไร้เดียงสาในการเลือกไฟล์ rc นั้นขึ้นอยู่กับ$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

สิ่งนี้จะใช้งานได้ก็ต่อเมื่อคุณเชื่อมต่อจากที่อยู่ IP เดียวกันตลอดเวลา ...

อีกวิธีที่ใช้ฟิลด์ข้อคิดเห็นของคีย์ 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เพื่อเลือกไฟล์ rc ไปยังแหล่งข้อมูลโดยตรงเช่นเดียวกับ$SUDO_USERวิธีการข้างต้น (ซึ่งความคิดเห็น$ssh_commentอาจจำเป็นต้องได้รับการล้างหากเป็นชื่อพา ธ ) หรือผ่านcaseคำสั่งเช่นเดียวกับ$SSH_CLIENTวิธีการ


การจับคู่SSH_CLIENTและSUDO_USERเป็นสิ่งที่ฉันใช้อยู่ในปัจจุบัน แต่ต้องมีการแก้ไขฝั่งเซิร์ฟเวอร์และไม่น่าเชื่อถือเป็นพิเศษ ฉันหวังว่าจะแก้ปัญหาฝั่งไคลเอ็นต์อย่างแท้จริง ขอบคุณสำหรับคำแนะนำว่า
Patrick

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 แต่ถ้าคุณต้องการพูดว่าการทันเนลพอร์ตนั่นอาจเป็นปัญหา


แต่ในกรณีใด ๆ ฉันคิดว่านี่ควรจะแก้ไขในระบบเป้าหมายด้วยบัญชีแยกต่างหาก ( sudoหรือเพียงแค่ UID เก่าธรรมดา 0) การกำหนดค่าส่วนบุคคลจะมีประโยชน์สำหรับกรณีอื่น ๆ เช่นกันและโดยทั่วไปคุณจะมีไฟล์กำหนดค่าและตัวแปรสภาพแวดล้อมมากมายที่คุณต้องการตั้งค่า (พิจารณาว่าผู้ดูแลระบบอาจไม่เห็นด้วยกับคุณค่าของ$EDITORหรือเนื้อหาของvircหรืออะไรก็ตาม)

การลบผู้ใช้จะทำได้ง่ายขึ้นด้วยบัญชีแยกต่างหาก

วิธีการทำข้อมูลให้ตรงกันไฟล์ในทุกครอบครัวใดจะยังนิดแก้ปัญหานี้โดยให้คุณสามารถเข้าสู่ระบบกับสิ่งที่ต้องการหรือssh -t user@host 'patricks_shell.sh'ssh -t user@host 'bash --rcfile patrick.rc'


ผมคิดว่าการใช้คาดหวัง interactแต่ในขณะที่คุณชี้แล้วออกมาในคำถามของคุณที่เป็นปัญหาที่ตรงกับสิ่งที่ไม่ซ้ำกันสำหรับพรอมต์ที่จะเริ่มต้น ไม่มีอยู่ข้อความแจ้งอาจแตกต่างกันเช่นเดียวกับ motds / output จากโปรไฟล์ ขอบคุณสำหรับคำแนะนำว่า
Patrick

1

คุณสามารถมีไฟล์ rc แบบกำหนดเองตามคู่มือนี้:

ไฟล์ rc ของผู้ใช้ Secure Shell: คำแนะนำที่ชัดเจน

หรือฉีดแอคชันบรรทัดคำสั่งในไฟล์ authorized_keys ของคุณ:

SSH config auto ดำเนินการคำสั่งระยะไกล | Unix & Linux Stack Exchange

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.