Как я могу автоматически изменить каталог при входе в систему через ssh?

87

Я пытаюсь sshавтоматически перейти в определенный каталог при входе в систему. Я пытался заставить это поведение работать, используя следующие директивы ~/.ssh/config:

Host example.net
LocalCommand "cd web"

но всякий раз, когда я вхожу, я вижу следующее:

/bin/bash: cd web: No such file or directory

хотя webв моем домашнем каталоге определенно есть папка. Даже использование абсолютного пути дает одно и то же сообщение. Чтобы было понятно, если я наберу cd webпосле входа в систему, я попадаю в нужную папку.

Что мне здесь не хватает?

РЕДАКТИРОВАТЬ:

Различные комбинации кавычек / абсолютных путей дают разные сообщения об ошибках:

LocalCommand "cd web"
/bin/bash: cd web: No such file or directory

LocalCommand cd web
/bin/bash: line 0: cd: web: No such file or directory

LocalCommand cd /home/gareth/web
/bin/bash: line 0: cd: /home/gareth/web: Input/output error

Это заставляет меня думать, что кавычек не должно быть, и что происходит другая ошибка.

Gareth
источник
9
LocalCommand запускается в вашей локальной системе, а не в удаленной системе.
Стив Келет
Смотрите здесь superuser.com/a/124110/47962
Накилон

Ответы:

25

CD - это встроенная оболочка. LocalCommand выполняется как:

/bin/sh -c <localcommand>

То, что вы хотите сделать, на самом деле не может быть достигнуто через SSH; вам нужно каким-то образом изменить оболочку, например, через bashrc / bash_profile.

<Редактирование почти десятилетие спустя ...>

LocalCommandне то, что вы хотите, в любом случае. Это работает на вашей машине. Вы хотите RemoteCommand. Как-то так у меня сработало

Host example.net
  RemoteCommand cd / && exec bash --login
  RequestTTY yes
BMDan
источник
1
Да, просто хотел упомянуть то же самое. Вместо этого вы можете ввести cdкоманду ~/.bashrcна удаленном сервере.
vdboor
Это раздражает. Как я уже упоминал в другом комментарии, на сервере есть несколько имен хостов, и я хотел иметь другое поведение в зависимости от используемого. Я думаю, что невозможно определить, какой был использован из .bashrc?
Гарет
Это возможно, просто, вероятно, не рекомендуется. Что-то вроде замены ssh небольшим сценарием оболочки или псевдонимом, который передает имя хоста как переменную для экспорта (а-ля "ssh -t user @ host 'export connhostname = host; bash --login'"). Но вы начинаете проникать в очень странную территорию, действительно. Возможно, лучше задать вопрос: ПОЧЕМУ вы хотите такого поведения?
BMDan
Это не так уж и сложно, если честно. Я просто нахожусь в ситуации, когда подавляющее большинство времени, когда я захожу на этот сервер, я направляюсь прямо в один из двух каталогов (в зависимости от того, какой хост я использую)
Гарет
77

Это работает:

ssh server -t "cd /my/remote/directory; bash --login"

Чтобы создать каталог, если он не существует:

ssh server -t "mkdir -p newfolder; cd ~/newfolder; pwd; bash --login"

Если вы не добавите bashв конец пути, вы выйдете после cdзапуска команды. И если вы не добавите, --loginто ваш ~/.profileне является источником.

Владислав Лежнев
источник
Это заканчивает меня в правильном местоположении, с подсказкой bash. идеальный!
Питер Эрлих
Это тоже работает для меня, но если я попытаюсь использовать его с ssh jump-host, это не сработает. Я получаю сообщение о закрытии соединения.
Риккардо,
43
  1. Войдите в вашу коробку
  2. редактировать ~/.bash_profile
  3. В конце файла добавьте cd /path/to/your/destination
  4. Сохранить и выйти
  5. Выйти из коробки
  6. Войдите снова и вы должны приземлиться на /path/to/your/destination
sobi3ch
источник
3
На некоторых машинах вам может понадобиться нужно добавить cd /path/to/your/destinationк ~/.bashrcвместо к ~/.bash_profile. Результат должен быть таким же.
Матиас
Это работает отлично, спасибо - это ограничено только моим идентификатором пользователя или это повлияет на вход других пользователей?
hard_working_ant
@BabyGroot, если вы измените ~/.bash_profileили ~/.bashrcэто повлияет только на текущего пользователя.
Рубенварела
5

Более надежное решение для случая, когда вам нужно ssh и переопределить файл .bashrc по умолчанию. Это полезно в тех случаях, когда среда удаленного сервера имеет несколько корневых узлов и используется несколькими пользователями.

alias ssh_myserver='ssh server_name -t "echo cd /path/to/desired/dir>/tmp/.bashrc_tmp; bash --rcfile /tmp/.bashrc_tmp"'

Более подробный:

  1. Первая команда создает .bashrc_tmpфайл в /tmpкаталоге на удаленном сервере с содержимымcd /path/to/dir
  2. Следующая команда выполняется bashс файлом конфигурации, указанным в шаге 1. Это позволяет переключиться на нужный каталог и подавить значение по умолчанию .bashrc.
  3. Вся эта команда упакована как a alias, поэтому в командной строке клиента ssh ее можно назватьssh_myserver
Алекс Скрипник
источник
Креатив ... до тех пор, пока вы пишете перманент в / tmp
smci
4

Вы включили эту директиву в конфигурации SSH?

PermitLocalCommand yes

По умолчанию это так no, и в этом случае ваша LocalCommandдиректива будет игнорироваться.

Или вы пытались добавить команду в свой .bashrcфайл?

EEAA
источник
Эта директива установлена, да (и я предполагаю, что я не увижу сообщение об ошибке, если оно не было). Проблема с использованием .bashrc заключается в том, что сервер имеет разные имена хостов, и я хотел бы, чтобы разные имена хостов транслировались в разные начальные каталоги
Gareth
Если у каждого имени хоста не свой IP-адрес, сервер не сможет узнать, какое имя хоста вы запрашивали. В то время как HTTP-запросы предоставляют дружественный заголовок Host: для идентификации запрошенного имени хоста, SSH-соединения этого не делают.
Fosco
4

Таким образом, я искал много сайтов (stackoverflow, этот), но не нашел то, что хотел. Я закончил тем, что создал свой собственный скрипт оболочки. Я вставляю это здесь. Также вы можете скопировать его в каталог в $ PATH.

#!/bin/bash
ssh -t <username@hostname> "cd ~/$1; exec \$SHELL --login"

Итак, после этого. Я делаю:

connect <foldername>

Примечание. Может потребоваться выйти из системы и войти снова после изменения переменной пути

ариец
источник
Я предпочитаю это предыдущему предложению, потому что «$ SHELL» всегда допустимо, а «bash» может и не быть. Также использование exec - приятное прикосновение.
Дейв
Дальнейшее уточнение должно было бы обеспечить, чтобы 'cd' был успешным - "cd ~ / $ 1 && exec ... '
Дейв
3

В вашем ~/.ssh/config:

LocalCommand echo '/home/%r/some/subdir' > /home/%r/.ssh/ssh_cd

В конце вашего ~/.bashrc:

if [[ -f $HOME/.ssh/ssh_cd ]]
then
    cd $(<$HOME/.ssh/ssh_cd)
    # uncomment the line below and the file will be removed so the cd won't work
    # unless the file is regenerated since you may not want this to operate for
    # non-ssh logins or for ssh logins that you want to function differently
    # rm $HOME/.ssh/ssh_cd
fi

Я пытался сделать это с помощью передачи переменных, в том числе с экспортированной переменной, но эти команды выполняются в разных оболочках.

При тестировании того, что вы пытались сделать, я не получил ошибку, когда, между прочим, использовал абсолютный путь без кавычек. Я добавил ; pwdв конце команды, и отображается правильный каталог, однако каталог, в котором я оказался, есть ~. В cdмоих файлах запуска оболочки нет команд. Я попытался положить другой cd somedir; pwdв ~/.ssh/rc(с другой все еще на месте). Команда configвыполняется до того, как будет выполнен motd, а rcкоманда будет выполнена позже, но до того, как будут получены файлы запуска оболочки. Опять же, это происходит в другой оболочке.

Попробуйте метод передачи по файлу и дайте мне знать, работает ли он для вас.

Деннис Уильямсон
источник
2

Вы пробовали это без кавычек вокруг этого? Единственные примеры, которые я видел, не имеют их, поэтому они могут пытаться выполнить cd \ web как команду.

Джеймс Л
источник
Хорошо, удаление кавычек, кажется, помогает, но у меня все еще есть ошибки (см. Отредактированное сообщение)
Гарет
1

Вы также можете попробовать это с опцией -t:

ssh server -t "cd /my/remote/directory; bash"
kenorb
источник
1

Попробуйте использовать RemoteCommandвместо, например,

Host myhost
  HostName IP
  User ubuntu
  IdentityFile ~/.ssh/id_rsa
  RemoteCommand cd web; $SHELL -il

RemoteCommand: Указывает команду для выполнения на удаленном компьютере после успешного подключения к серверу. ( man ssh_config)

kenorb
источник