sh tập tin khởi động qua ssh


10

Tôi có một số lệnh quan trọng tôi cần thực hiện trước khi bất kỳ shell sh nào bắt đầu. Điều này là cần thiết để truyền các lệnh SSH trong lệnh SSH ( ssh host somecommand) và các chương trình khác chạy các lệnh.

Trong tôi .profilecó cái này:

ihammerhands@wreckcreations:~> cat .profile
#specific environment and startup programs
export PS1="\u@wreckcreations:\w> "
export PYTHONPATH=~/python/lib/python2.4/site-packages
export PATH=$PATH:~/bin:~/python/bin

Tuy nhiên, điều này không thành công:

W:\programming\wreckcreations-site\test-hg>ssh name@host echo $PATH
Enter passphrase for key '/home/Owner/.ssh/id_rsa':
/usr/local/bin:/bin:/usr/bin

Lưu ý các tùy chọn PATH bị thiếu

Tên thích hợp cho hồ sơ sh là gì? Lưu ý: Tôi không có quyền truy cập root và không muốn áp dụng điều này cho người dùng khác. Có một cách khác để làm điều này?


EDIT: Nó xuất hiện /bin/shcác liên kết đến bash, điều này không gây ngạc nhiên. Điều đáng ngạc nhiên là hồ sơ của tôi vẫn bị bỏ qua. Bất kỳ đề xuất?


1
Tôi không cảm thấy muốn lặp lại những gì trong trang man, vì vậy chỉ cần nhìn vào trang bash man trong phần 'HÓA ĐƠN'. Nó ở gần đầu và mô tả tất cả những gì bạn cần biết.
CAMH

Bạn có thể thử sử dụng ssh name@host -t echo $PATH.
Gert

@Gert Kết quả giống nhau
TheLQ

@camh Bạn có nghĩ tôi sẽ hỏi câu hỏi này nếu tôi chưa kiểm tra trang nam không? Tôi đã đọc chúng nhiều lần + các bài đăng khác nhưng không bao giờ có thể tìm thấy câu trả lời cho vấn đề cụ thể này, vì tôi không chắc các lệnh ssh giai đoạn nào và các lệnh khác của chương trình được thực thi trong
TheLQ

1
@TheLQ: Tôi không biết bạn vì vậy tôi không biết nếu bạn sẽ kiểm tra trang người đàn ông. Tất cả những gì tôi biết là câu trả lời đã ở ngay đó, vì vậy thay vì lặp lại từng chữ, tôi chỉ cho bạn biết. Một con trỏ cụ thể hơn là tìm kiếm các shell không tương tác vì đó là kịch bản ssh của bạn. Nếu một cái gì đó trong trang người đàn ông không rõ ràng, có lẽ bạn có thể hỏi một câu hỏi cụ thể hơn.
camh

Câu trả lời:


8

Có vẻ đáng lưu ý rằng lệnh bạn đề cập trong câu hỏi của bạn

ssh name@host echo $PATH

sẽ không bao giờ có ích Việc thay thế biến cho $ PATH được thực hiện bởi trình bao cục bộ của bạn và được chuyển đến ssh để thực hiện tiếng vang trên hệ thống từ xa để in nội dung của biến đường dẫn, khi nó được mở rộng trên hệ thống cục bộ của bạn. Đây là một ví dụ về việc tôi làm một cái gì đó tương tự giữa máy Mac và máy Linux trên mạng của tôi:

LibMBP:~ will$ echo $PATH
/opt/local/bin:/opt/local/sbin:/Users/will/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
LibMBP:~ will$ ssh warren echo $PATH
will@warren's password: 
/opt/local/bin:/opt/local/sbin:/Users/will/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
LibMBP:~ will$ ssh warren 'echo $PATH'
will@warren's password: 
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
LibMBP:~ will$ 

Lưu ý cách tôi cần sử dụng dấu ngoặc kép để ngăn shell cục bộ của tôi mở rộng biến.


Trong vùng đất Cygwin của Windows, các trích dẫn đơn lẻ không làm gì trong dấu nhắc Cygwin hoặc Command. Thật kỳ lạ, dấu ngoặc kép làm cho PATH mở rộng hoàn toàn sang máy cục bộ của tôi ở Cygwin. Vì vậy, bất cứ điều gì ssh đã cho tôi không phải là con đường của tôi, đó là của máy chủ
TheLQ

@TheLQ Các trích dẫn đơn là cần thiết tại dấu nhắc unix (bao gồm cả Cygwin), nhưng bạn không cần bất kỳ dấu ngoặc kép nào tại dấu nhắc cmd.
Gilles 'SO- ngừng trở nên xấu xa'

12

~/.profilechỉ được thực hiện bởi shell đăng nhập. Chương trình gọi shell quyết định xem shell có phải là shell đăng nhập hay không (bằng cách đặt -ký tự đầu tiên của đối số zeroth vào lệnh gọi shell). Nó thường không được thực thi khi bạn đăng nhập để thực thi một lệnh cụ thể.

OpenSSH đặc biệt gọi vỏ đăng nhập chỉ khi bạn không chỉ định lệnh. Vì vậy, nếu bạn chỉ định một lệnh, ~/.profilesẽ không được đọc.

OpenSSH cho phép thiết lập các biến môi trường ở phía máy chủ. Điều này phải được kích hoạt trong cấu hình máy chủ , với PermitUserEnvironmentchỉ thị. Các biến có thể được đặt trong tệp ~/.ssh/environment. Giả sử bạn sử dụng xác thực khóa chung, bạn cũng có thể đặt biến per-key trong ~/.ssh/authorized_keys: add environment="FOO=bar"ở đầu dòng có liên quan.

Ssh cũng hỗ trợ gửi các biến môi trường. Trong OpenSSH, sử dụng SendEnvchỉ thị trong ~/.ssh/config. Tuy nhiên, biến môi trường cụ thể phải được bật bằng một lệnh AcceptEnvtrong cấu hình máy chủ, vì vậy điều này có thể không phù hợp với bạn.

Một điều mà tôi nghĩ luôn luôn hoạt động (đủ kỳ lạ) miễn là bạn đang sử dụng xác thực khóa chung là (ab) sử dụng command=tùy chọn trong authorized_keystệp . Một khóa với một commandtùy chọn chỉ tốt khi chạy lệnh được chỉ định; nhưng lệnh trong authorized_keystệp chạy với biến môi trường SSH_ORIGINAL_COMMANDđược đặt thành lệnh do người dùng chỉ định. Biến này trống nếu người dùng không chỉ định lệnh và do đó mong đợi một vỏ tương tác. Vì vậy, bạn có thể sử dụng một cái gì đó như thế này ~/.ssh/authorized_keys(tất nhiên, nó sẽ không áp dụng nếu bạn không sử dụng khóa này để xác thực):

command=". ~/.profile; if [ -n \"$SSH_ORIGINAL_COMMAND\" ]; then eval \"$SSH_ORIGINAL_COMMAND\"; else exec \"$SHELL\"; fi" ssh-rsa 

Một khả năng khác là viết một tập lệnh bao bọc trên máy chủ. Một cái gì đó như sau ~/bin/ssh-wrapper:

#!/bin/sh
. ~/.profile
exec "${0##*/}" "$@"

Sau đó tạo các liên kết tượng trưng cho tập lệnh này được gọi rsync, unisonv.v. Truyền --rsync-path='bin/rsync'vào rsyncdòng lệnh, v.v. cho các chương trình khác. Ngoài ra, một số lệnh cho phép bạn chỉ định toàn bộ đoạn mã shell để chạy từ xa, cho phép bạn đặt lệnh độc lập: ví dụ: với rsync, bạn có thể sử dụng --rsync-path='. ~/.profile; rsync'.

Có một con đường khác phụ thuộc vào vỏ đăng nhập của bạn là bash hoặc zsh. Bash luôn đọc ~/.bashrckhi nó được gọi bởi rshd hoặc sshd, ngay cả khi nó không tương tác (nhưng không được gọi là as sh). Zsh luôn đọc ~/.zshenv.

## ~/.bashrc
if [[ $- != *i* ]]; then
  # Either .bashrc was sourced explicitly, or this is an rsh/ssh session.
  . ~/.profile
fi

## ~/.zshenv
if [[ $(ps -p $PPID -o comm=) = [rs]shd && $- != *l* ]]; then
  # Not a login shell, but this is an rsh/ssh session
  . ~/.profile
fi

Điều gì về các lệnh mà các lệnh khác thực hiện? Trong trường hợp này, nó sẽ là móc Mercurial. Mercurial cần phải trên con đường để móc nối thậm chí nghĩ đến việc làm
TheLQ

Sử dụng bất kỳ kỹ thuật nào tôi đã chỉ định để hồ sơ của bạn chạy trong các lệnh ssh không tương tác. Một trong số họ ( command=trong authorized_keys) hoạt động minh bạch. Những người khác yêu cầu một vỏ cụ thể hoặc các tùy chọn trong cấu hình máy chủ ssh. Tương đương Mercurial --rsync-path--remotecmd.
Gilles 'SO- ngừng trở nên xấu xa'

Nó có thể hữu ích với một số người để bao gồm cùng một command=lệnh đầy đủ như trong bài đăng của bạn superuser.com/a/207262/137762
mforbes

1

Thông thường khi đăng nhập, bash đọc các lệnh từ:

~ / .bash_profile
~ / .bashrc

Từ trang bash man:

~ / .bash_profile
Tệp khởi tạo cá nhân, được thực thi cho shell đăng nhập

~ / .bashrc
Tệp khởi động mỗi vỏ tương tác riêng lẻ


0

Tôi đã hết thời gian để kiểm tra điều này, nhưng nhìn qua các trang người đàn ông tôi tìm thấy:

man bash: Ví dụ, khi bash được khởi động không tương tác, để chạy tập lệnh shell, nó tìm biến BASH_ENV trong môi trường, mở rộng giá trị của nó nếu nó xuất hiện ở đó và sử dụng giá trị mở rộng làm tên của tệp đọc và thực hiện. Bash hành xử như thể lệnh sau được thực thi: if [-n "$ BASH_ENV"]; sau đó . "$ BASH_ENV"; fi nhưng giá trị của biến PATH không được sử dụng để tìm kiếm tên tệp.

man ssh: ~ / .ssh / môi trường Chứa các định nghĩa bổ sung cho các biến môi trường; xem MÔI TRƯỜNG, ở trên.

Sự kết hợp cho thấy làm thế nào bạn có thể có ssh thực thi .profile của bạn

Thật không may, máy chủ của tôi có PermitUserEn Môi trường với giá trị mặc định là không, điều này làm cho nó không hoạt động với tôi (và như tôi đã nói tôi không có thời gian để chơi với nó nhiều hơn).


Ngay cả khi tôi có thể khiến SSH hoạt động bằng cách nêu rõ một số biến môi trường trong môi trường, nó vẫn không giúp sửa lỗi khiến hồ sơ của tôi được thực thi khi các chương trình khác gọi lệnh
TheLQ

Trong ví dụ của bạn, tất cả những gì bạn đang làm là thiết lập các biến môi trường, bạn còn muốn làm gì nữa?
kasterma

0

(đã xóa ... chỉ có thể có một Siêu liên kết là người dùng mới ~)

Cập nhật

Xin lỗi, tôi không thấy rằng đây là về một phiên không tương tác, mà liên kết trên không áp dụng.

Khi Bash bắt đầu ở chế độ tương thích SH, nó cố gắng bắt chước hành vi khởi động của các phiên bản lịch sử của sh càng gần càng tốt, đồng thời tuân thủ tiêu chuẩn POSIX®. Các tệp hồ sơ được đọc là / etc / profile và ~ / .profile, nếu đó là vỏ đăng nhập.

Nếu nó không phải là vỏ đăng nhập, biến môi trường ENV được ước tính và tên tệp kết quả được lấy làm tên của tệp khởi động.

Sau khi các tệp khởi động được đọc, Bash vào chế độ tương thích POSIX (r) (để chạy, không phải để bắt đầu!).

Bash bắt đầu trong chế độ tương thích sh khi:

  • tên tệp cơ sở trong argv [0] là sh (:!: Chú ý người dùng Linux thông minh uber ... / bin / sh có thể được liên kết với / bin / bash, nhưng điều đó không có nghĩa là nó hoạt động như / bin / bash :! :)

Vì vậy, câu hỏi là, tại sao nó không thực thi nó, mặc dù vỏ của bạn được bắt đầu như thế này.

Nguồn


Tôi đã xem nhưng như tôi đã nói với camh Tôi không biết các lệnh ssh giai đoạn nào và các lệnh chương trình khác được thực thi. Tôi đã đọc các trang hướng dẫn và các hướng dẫn khác nhiều lần rồi
TheLQ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.