Cập nhật biến môi trường phiên màn hình để phản ánh đăng nhập đồ họa mới?


20

Tôi sử dụng linux và tôi muốn thực hiện tất cả các công việc dòng lệnh của mình trong một phiên màn hình duy nhất, để tôi có thể khởi động lại đăng nhập đồ họa của mình và như vậy mà không mất các thiết bị đầu cuối. Tuy nhiên, khi tôi đăng xuất và quay lại phiên đồ họa của mình, điều này sẽ thay đổi tất cả các biến môi trường phiên của tôi, chẳng hạn như các phiên DBus. Điều này có nghĩa là sau khi đăng nhập lại, phiên màn hình của tôi bây giờ có các biến môi trường cũ (và sai). Vì vậy, bây giờ khi tôi cố gắng bắt đầu các chương trình đồ họa từ phiên màn hình của mình, tốt nhất là chúng sẽ phát ra cảnh báo về việc không thể kết nối với bus phiên. Tồi tệ nhất, họ thất bại để bắt đầu hoàn toàn.

Vì vậy, những gì tôi đang tìm kiếm là một cách để sửa đổi các biến môi trường trong một phiên bản đang chạy của màn hình, để tất cả các cửa sổ màn hình được tạo sau đó sẽ kế thừa các biến môi trường mới. Có cách nào để làm việc này không?


3
Aha! Tôi chỉ xem qua toàn bộ trang web để tìm cái này:setenv [var [string]] Set the environment variable var to value string. If only var is specified, the user will be prompted to enter a value. If no parameters are specified, the user will be prompted for both variable and value. The environment is inherited by all subsequently forked shells.
Ryan C. Thompson

Người ta có thể gọi setenv bằng cách sử dụng chuyển đổi -X sang màn hình. Than ôi, nó chỉ hoạt động trên tất cả các vỏ sau đó, không phải trên vỏ hiện tại.
Boris Bukh

Lưu ý rằng byobu hiện kết hợp một giải pháp cho việc này cho cả màn hình và tmux.
Ryan C. Thompson

Câu trả lời:


8

Bạn không thể bắt đầu một tập lệnh shell từ screenphiên vì nó sẽ kế thừa môi trường cũ. Tuy nhiên, bạn có thể cho chúng tôi một fifo để đưa các biến môi trường mới vào phiên màn hình cũ. Bạn có thể điền vào fifo khi bạn bắt đầu phiên đồ họa của mình.

#!/bin/bash
FIFO=/tmp/your_variables
[ -e $FIFO ] && cat $FIFO > /dev/null || mkfifo $FIFO

# save number of variables that follow
NVARS=2
echo $NVARS > $FIFO
echo ENV1=sth1 > $FIFO
echo ENV2=sth2 > $FIFO

Bắt đầu tập lệnh đó trong nền khi đăng nhập (nó sẽ chỉ chấm dứt khi tất cả các biến được đọc từ nó).

Bây giờ bạn có thể đọc từ fifo, ví dụ: thêm chức năng này vào .bashrc

update_session() {
  FIFO=/tmp/your_variables

  NVAR=$(cat $FIFO)
  for i in $(seq $NVAR); do
    export $(cat $FIFO)
  done
  #delete the pipe, or it will not work next time 
  rm $FIFO
}

để bạn có thể trong screenphiên cũ của bạn

update_session

bạn sẽ không cần phải làm điều này một lần trên mỗi cửa sổ trong phiên chạy để sửa đổi vỏ chính của cửa sổ chứ?
quack quixote

Đẹp, mặc dù như ~ quack nói, bạn cần phải cập nhật từng shell một cách độc lập.
dmckee

Phải, bạn cần phải làm điều đó trong mỗi vỏ trong screen. AFAIK screenkhông có ổ cắm hoặc tương tự để giao tiếp với các phiên chạy từ bên ngoài.
Benjamin Bannier

@dmckee nhưng tất nhiên mỗi phiên mới screen đã có các biến môi trường gần đây
Benjamin Bannier

Tôi đã quyết định chỉ chấp nhận câu trả lời này ngay bây giờ. Nếu tôi có thể thực hiện điều này, tôi sẽ cập nhật. Nhưng bây giờ, chỉ cần có cảm giác mờ ấm khi biết rằng về mặt lý thuyết là có thể.
Ryan C. Thompson

2

Tôi đã thực hiện một kịch bản để làm điều này. Bạn có thể lấy nó ở đây: https://github.com/DarwinAwardWinner/screen-sendenv

Sau khi đưa screen-sendenv.pyvào $PATH, bạn có thể sử dụng đoạn mã sau trong .bashrc:

VARS_TO_UPDATE="DISPLAY DBUS_SESSION_BUS_ADDRESS SESSION_MANAGER GPG_AGENT_INFO"
screen_pushenv () {
  screen-sendenv.py -t screen $VARS_TO_UPDATE
}
tmux_pushenv () {
  screen-sendenv.py -t tmux $VARS_TO_UPDATE
}
screen_pullenv () {
  tempfile=$(mktemp -q) && {
    for var in $VARS_TO_UPDATE; do
      screen sh -c "echo export $var=\$$var >> \"$tempfile\""
    done
    . "$tempfile"
    rm -f "$tempfile"
  }
}
tmux_pullenv () {
  for var in $VARS_TO_UPDATE; do
    expr="$(tmux showenv | grep "^$var=")"
    if [ -n "$expr" ]; then
      export "$expr"
    fi
  done
}

Để sử dụng nó, chỉ cần chạy screen_pushenvtrước khi bạn chạy screen -rđể gắn lại vào phiên màn hình của bạn. Sau đó, sau khi đính kèm screen -r, bạn có thể cập nhật môi trường trong các shell hiện có của mình với screen_pullenv. Các chức năng tmux thực hiện điều tương tự cho tmux, một bộ ghép kênh đầu cuối khác tương tự như màn hình.


Wow Ryan, đó là rất nhiều mã. Điều gì đã sai với câu trả lời được chấp nhận trước đó (ít nhất nó đã truyền cảm hứng)?
Benjamin Bannier

1
Chà, tôi phát hiện ra rằng màn hình (và cả tmux) có lệnh "setenv" đặt biến môi trường cho chính màn hình, chứ không phải vỏ trong cửa sổ màn hình hiện tại. Vì vậy, điều đó có nghĩa là sau khi bạn sử dụng tập lệnh của tôi, tất cả các cửa sổ mới được tạo trong phiên màn hình đó sẽ tự động nhận được môi trường mới mà không phải chạy tập lệnh cập nhật trong mỗi tập lệnh. Tất nhiên, một tập lệnh cập nhật vẫn có thể hữu ích cho việc cập nhật các shell hiện có, nhưng bạn phải viết lại nó không phải để đọc từ một FIFO, mà là để truy vấn chính phiên / tmux cho các giá trị mới.
Ryan C. Thompson

Bạn có thể xem cách kéo biến vào trình bao hiện tại từ phiên màn hình / tmux tại đây , trong screen_updatevà các tmux_updatehàm. Tôi sẽ cập nhật câu trả lời của tôi với phiên bản độc lập của byobu.
Ryan C. Thompson

1
Dù sao, để trả lời trực tiếp câu hỏi của bạn về những gì sai, câu trả lời của bạn không hoàn toàn trả lời câu hỏi, mà là trả lời một câu hỏi liên quan. Bạn chỉ ra cách cập nhật các biến môi trường bên trong một vỏ chạy trong phiên màn hình, nhưng không cập nhật các biến môi trường trong phiên màn hình (như các cửa sổ mới được sinh ra kế thừa các giá trị mới). Tôi đã chấp nhận nó vào thời điểm đó bởi vì nó vẫn là một giải pháp tốt, nhưng tôi luôn có ý định cuối cùng thực hiện một câu trả lời thực sự cho câu hỏi của tôi khi được hỏi . Vì vậy, không có gì cá nhân.
Ryan C. Thompson

Này Ryan, cảm ơn vì đã trả lời. Bây giờ bạn đề cập setenvtôi thấy làm thế nào là tốt hơn. Không rõ ràng từ mã bạn liên kết đến. Cảm ơn một lần nữa!
Benjamin Bannier

2

Bạn có thể gọi setenvlệnh để thay đổi các biến môi trường trong quy trình màn hình một cách tương tác, bằng cách sử dụng: Ctrl- A+ :setenv(Lưu ý :ký tự để nhập lệnh màn hình.) Bạn sẽ được nhắc nhập tên và giá trị của biến môi trường.

Lưu ý rằng (theo các câu trả lời / nhận xét khác) điều này ảnh hưởng đến quá trình màn hình (cha mẹ) và do đó các phiên màn hình mới được tạo, nhưng không phải là phiên màn hình hiện tại của bạn cũng như bất kỳ phiên màn hình hiện tại nào.

Bạn có thể chỉ định tên và giá trị của biến môi trường cùng một lúc nếu bạn muốn: Ctrl- A+ :setenv DISPLAY :100. Sẽ đặt HIỂN THỊ thành ": 100" cho các phiên màn hình mới.

Để xóa biến môi trường, bạn có thể sử dụng 'unsetenv' - vd Ctrl- A+:unsetenv DISPLAY


0

Đây có lẽ là một giải pháp đơn giản hơn (bạn quyết định). Phần quan trọng là bí danh gọi savedisplayhàm mỗi khi screenlệnh được chạy. Các lệnh không được chạy tự động, do đó có thể được đưa vào ~/.bashrcthay vì một cái gì đó rất chuyên dụng như ~/.ssh/rc.

savedisplay() {
    # Write latest bash display to a file, This is used to 
    # update running bash sessions for a "screen -r"
    echo "export DISPLAY=$DISPLAY" > ~/.XDISPLAY
    echo "export XAUTHORITY=$XAUTHORITY" >> ~/.XDISPLAY
    # This will only update the environment for new windows
    screen -X setenv DISPLAY $DISPLAY
    screen -X setenv XAUTHORITY $XAUTHORITY
}

# run this to update env variable in a running session
updatedisplay() {
    source ~/.XDISPLAY 
}

alias screen='savedisplay && screen'
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.