Bir sisteme giriş yaptıktan sonra bash readline'ı otomatik olarak vi moduna nasıl ayarlayabilirim?


9

Ekibim binlerce Linux / Unix makinesinden sorumludur, bu nedenle kök hesabı yöneticiler arasında "paylaşılır". Vi modunu, diğerleri emacs modunu tercih ederim.

SSH'yi herhangi bir makineye giriş yaptıktan sonra, herkesin vi modunu kullanmaya zorlamadan bash'ın readline'ını vi moduna nasıl ayarlayabilirim?

set -o viAslında, giriş yaptıktan sonra her seferinde yazmak zorunda kalmadan ve herkese zorlamadan (emacs modu benim için can sıkıcı olduğu için, vi modu onlar için can sıkıcıdır) etkisine sahip olmak ister.

Herkes ayrıcalıklı komutları yürütmek için sudo ile kendi hesaplarını kullanırsa bunun bir sorun olmayacağını biliyorum, ancak kontrolüm dışındaki koşullar nedeniyle bu ne yazık ki bir seçenek değil.


1
Bu kolay değil. Bir yol, sshd'nin günlük dosyasını ayrıştırmak ve oturum açmak için hangi anahtarın kullanıldığını görmek. Bir istemci tarafı çözümü umuyordum, örneğin yerel readline yapılandırmamı uzak tarafa veya bunun gibi bir şeye geçirmenin bir yolu veya set -o viKabuğun kontrolünü bana vermeden önce sessizce çalışan karanlık OpenSSH büyüsü .
Patrick

1
Belki istemcide sunucuya ssh olan bir Expect betiği kullanabilir, set -o vikomutu gönderebilir , sonra etkileşimli moda geçebilirsiniz .
Barmar

1
En azından OpenSSH sshd, diğer tarafta kimin olduğunu belirlemenize yardımcı olabilecek çeşitli ortam değişkenleri ayarlar. Örneğin SSH_CLIENT, bağlanan IP adresini (ve istemcinin giden / gelen bağlantı noktasını da içerir) içerir. Bununla uğraşmak, sadece~/.bashrc sizin için bir şeyler yapmanıza izin verebilir .
Sami Laine

1
Ödül, "müşteri tarafı çözümü" aradığınızı söylüyor - bu nedir? Unix ana bilgisayarında ssh? Macun? Hummingbird? Java SSH? Cygwin?
Jeff Schaller

1
On binlerce makineden bahsediyorsunuz. Bir makineden başlamak ve bu makinelere gitmek ister misiniz, yoksa sizinle vi modunu taşıyan makineden makineye makineye atlamak ister misiniz?
icarus

Yanıtlar:


3

Bunu yapmak için aptalca bir yol var, bu da sadece ortak anahtar kimlik doğrulamasıyla gerçekten iyi çalışıyor:

İlk olarak, yerel makinenizin ncüzerinde olduğundan emin olun .

İkincisi, hala yerel makinenizde, bir komut dosyası yapın (onu arayacağım connect-to-server) ve ${PATH}* * hakkında bildiğiniz bir yere koyun :

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

Ardından, .bashrcuzaktaki sistemde bir yere dahil olacak şekilde değiştirin :

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

Son olarak, yerel makinenize geri dönmek için düzenleyin ~/.ssh/config:

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

Bu yaklaşımın dezavantajları (ve neden aptalca diyorum):

  • Gerçek bir proxy komutu gerekiyorsa, daha karmaşık hale gelir.
  • Aynı anda başka biri de oturum açarsa, .yournamedosyanın henüz silinmemiş olması ihtimali vardır, bu durumda da bunu alırlar set -o vi.
  • En önemlisi, yaparsanız ssh serverNickname command, o commandzaman çalışır, ancak ( .bashrcasla kaynaklanmadığı için) .yournamedosya kalır, bu nedenle ssh yapılandırmada sözde proxy kullanmayan ikinci bir diğer adın olması kibar olacaktır.

Aslında, bu yaklaşımın tek tarafı sshkomutunuza fazladan argüman verilmesi gerekmemesidir.


* Uzak sistemlerde herhangi bir değişiklik yapmak istemiyorsanız, geçici bir alternatif oluşturan sahte bir proxy aşağıda verilmiştir .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

Bu, diğer yöntemin tüm dezavantajlarına sahiptir, bu nedenle yine de sshyapılandırmanızda sözde proxy'yi çalıştırmayan ikinci bir diğer ad istersiniz .


Çok yaratıcı. Öneri için teşekkürler. ProxyCommand'ı zaten zaten kullanıyorum (bazı ağlar / ana bilgisayarlar ulaşmak için 5+ atlama gerektirir) ve bu hızla bir yapılandırma kabusu ile sonuçlanır. Edit: Sanırım tüm cevaplara en yakın geliyor.
Patrick

4

Ben giderdim:

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

ancak yönetici sizsiniz, daha temiz bir şey deneyebilirsiniz. Örneğin SendEnv, belirli bir değişkeni iletmek için istemci tarafındaki ssh seçeneğini kullanabilir AcceptEnv, sshdkabul etmek için yapılandırmada (sunucu tarafı) kullanabilir ve buna dayanarak .bashrcdavranışı değişkenin değerine göre ayarlamak için kök dosyasını değiştirebilirsiniz .

Bu sshd, tüm ana bilgisayarların yanı sıra yapılandırmaları da değiştirmeyi gerektirir .bashrc. Tam olarak "bağımsız" bir yol değil, ancak ...


3

Kolay istemci tarafı çözümü için:

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

Bu başarısız olur eğer root kabuk başlatma komut açıkça kullanımları set -o emacsveya kümeler EDITORiçin emacsveya root eğer .initrcdosya çağırır emacstuş bağları.

Bu cevabın geri kalanı sunucu tarafındaki çözümlerle ilgilidir.


Bu ssh, makineye girip sonra kullandığınızda çalışır sudo -i:

Sizin için /root/.bashrc:

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

Bu, kişisel bir bashrcdosyaya sahip olmanıza izin verir , /root/.bashrc-patrickburada istediğiniz gibi yapabilirsiniz set -o vi.

Bunu, rc dosyasını almak için biraz naif bir yaklaşımla birleştirmek $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

Bu, yalnızca aynı IP adresinden her zaman bağlanıyorsanız çalışır ...

SSH aracısını sunucuya yönlendiriyorsanız çalışan SSH anahtarının yorum alanını kullanan başka bir yaklaşım:

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

Bu, sunucuya bağlanmak için kullandığınız anahtarın yorum alanını seçer. head -n 1Daki tuşların birkaç var ne durumda olduğunu authorized_keysdosyası.

Daha sonra $ssh_comment, doğrudan $SUDO_USERyukarıdaki yaklaşımda olduğu gibi ( $ssh_commentbir yol adı ise yorumun bazı temizleme işlemlerine tabi tutulması gerekebilir) ya caseda $SSH_CLIENTyaklaşımdaki gibi bir ifade yoluyla kaynağa bir rc dosyası seçmek için kullanabilirsiniz .


Eşleştirme SSH_CLIENTve SUDO_USERşu anda kullandığım şey, ancak sunucu tarafında değişiklik gerektiriyor ve özellikle güvenilir değil. Saf bir istemci tarafı çözümü umuyordum. Ancak öneri için teşekkür ederiz.
Patrick

3

Gerçekten sunucu tarafında değişiklik yapmadan yapmak istiyorsanız, aşağıdakilerden birini yapın:

1) Gibi bir şey çalıştırın

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

Belgelerin bu konuda çok açık olduğunu düşünmüyorum , ancak -o optionbahsedildi ve işe yarıyor gibi görünüyor.

2) Kullanım beklentisi:

expectkomut:

$ 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

Yürütülebilir hale getirin ve çalıştırın:

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

Bu, parola girmeden (uzak ana bilgisayar veya anahtarlarınız için) oturum açabileceğinizi varsayar, aksi takdirde beklenen komut dosyasının bunu dikkate alması gerekir. Ancak birçok makinede buna zaten sahip olacaksınız. Ayrıca, beklenen senin istemi göre bir dolar işareti ve bir boşluk, düzenleme için: "# "belki.

Bilgi isteminden önce yazdırılan bir şey aynı karakterleri içeriyor olsa da, beklenen dizeye daha spesifik bir şey eklemeniz gerekir.

Ayrıca, bu komut dosyası fazladan argüman verilmesini desteklemez ssh. Çalıştırmak için açık bir komut verecekseniz, büyük olasılıkla vi moduna ihtiyacınız yoktur, ancak bağlantı noktası tünellemesine ihtiyacınız varsa, bu bir sorun olabilir.


Ancak her durumda, bunun ayrı hesaplara sahip hedef sistemlerde ( sudoveya yalnızca eski UID 0) çözülmesi gerektiğini düşünüyorum . Kişiselleştirilmiş yapılandırma diğer birçok durum için de yararlı olacaktır ve genel olarak ayarlamak istediğiniz bir grup yapılandırma dosyası ve ortam değişkeniniz olacaktır. (Yöneticilerin değeri $EDITORveya içeriği vircya da herhangi bir şey konusunda anlaşamayabileceğini düşünün .)

Ayrıca, ayrı hesaplarla kullanıcıları kaldırmak daha kolay olurdu.

Tüm ana bilgisayarlardaki dosyaları senkronize etmenin herhangi bir yolu, ssh -t user@host 'patricks_shell.sh'veya gibi bir şeyle giriş yapmanıza izin vererek bunu önemsiz bir şekilde çözecektir ssh -t user@host 'bash --rcfile patrick.rc'.


Beklentiyi kullanmayı düşündüm, ancak sorunuzda zaten belirttiğiniz gibi, sorun, istemin başlaması için benzersiz bir şeyle eşleşiyor interact. Mevcut değil, istemler, profillerden gelen motifler / çıktılar gibi çok farklı olabilir. Yine de öneri için teşekkürler.
Patrick

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.