กำลังอัปเดตตัวแปรสภาพแวดล้อมเซสชันหน้าจอเพื่อแสดงการเข้าสู่ระบบแบบกราฟิกใหม่หรือไม่


20

ฉันใช้ linux และฉันต้องการทำงานบรรทัดคำสั่งทั้งหมดในเซสชันหน้าจอเดียวเพื่อให้ฉันสามารถเริ่มต้นการเข้าสู่ระบบแบบกราฟิกของฉันและทำเช่นนี้โดยไม่สูญเสียอาคารของฉัน อย่างไรก็ตามเมื่อฉันออกจากระบบและกลับสู่เซสชันกราฟิกของฉันสิ่งนี้จะเปลี่ยนแปลงตัวแปรสภาพแวดล้อมเซสชันทั้งหมดของฉันเช่นเซสชัน DBus ซึ่งหมายความว่าหลังจากเข้าสู่ระบบอีกครั้งเซสชันหน้าจอของฉันในขณะนี้มีตัวแปรสภาพแวดล้อมแบบเก่า (และผิด) ดังนั้นเมื่อฉันพยายามเริ่มโปรแกรมกราฟิกจากหน้าจอของฉันที่ดีที่สุดพวกเขาส่งเสียงเตือนว่าไม่สามารถเชื่อมต่อกับเซสชันบัสได้ ที่เลวร้ายที่สุดพวกเขาล้มเหลวในการเริ่มต้นอย่างสมบูรณ์

ดังนั้นสิ่งที่ฉันกำลังมองหาคือวิธีการปรับเปลี่ยนตัวแปรสภาพแวดล้อมในอินสแตนซ์ที่กำลังทำงานของหน้าจอเพื่อให้หน้าต่างหน้าจอที่สร้างขึ้นในภายหลังทั้งหมดจะสืบทอดตัวแปรสภาพแวดล้อมใหม่ มีวิธีทำเช่นนี้หรือไม่?


3
Aha! ฉันเพียงเพจผ่าน manpage ทั้งหน้าเพื่อค้นหาสิ่งนี้: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

หนึ่งสามารถเรียกใช้ setenv โดยใช้ -X สลับไปที่หน้าจอ อนิจจามันใช้ได้เฉพาะกับเชลล์ที่มีการแยกทั้งหมดในภายหลังเท่านั้นไม่ใช่บนเชลล์ปัจจุบัน
Boris Bukh

โปรดทราบว่าตอนนี้byobu ได้รวมโซลูชันสำหรับทั้งหน้าจอและ tmux
Ryan C. Thompson

คำตอบ:


8

คุณไม่สามารถเริ่มเชลล์สคริปต์จากscreenเซสชันเนื่องจากจะสืบทอดสภาพแวดล้อมเก่า อย่างไรก็ตามคุณสามารถให้เราห้าสิบเพื่อรับตัวแปรสภาพแวดล้อมใหม่ในเซสชั่นหน้าจอเก่า คุณสามารถกรอก Fifo นั้นได้เมื่อคุณเริ่มเซสชันกราฟิกของคุณ

#!/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

เริ่มสคริปต์นั้นในพื้นหลังในการเข้าสู่ระบบ (มันจะจบลงเมื่อตัวแปรทั้งหมดจะถูกอ่านจากมัน)

ตอนนี้คุณสามารถอ่านจาก Fifo ได้เช่นเพิ่มฟังก์ชั่นนี้ลงในของคุณ .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
}

เพื่อให้คุณสามารถในscreenเซสชั่นเก่าของคุณ

update_session

คุณไม่จำเป็นต้องทำเช่นนี้หนึ่งครั้งต่อหนึ่งหน้าต่างในเซสชันที่กำลังทำงานเพื่อแก้ไขเชลล์หลักของหน้าต่าง
ต้มตุ๋น quixote

ดีแม้ว่า ~ quack บอกว่าคุณต้องอัปเดตแต่ละเชลล์อย่างอิสระ
dmckee

screenขวาคุณจะต้องทำในแต่ละเปลือกใน AFAIK screenไม่มีซ็อกเก็ตหรือคล้ายกันในการสื่อสารกับเซสชันการทำงานจากภายนอก
Benjamin Bannier

@dmckee แต่แน่นอนทุกเซสชันใหม่ screenมีตัวแปรสภาพแวดล้อมที่ผ่านมาแล้ว
Benjamin Bannier

ฉันตัดสินใจที่จะยอมรับคำตอบนี้ในตอนนี้ หากฉันเคยชินกับการนำสิ่งนี้ไปใช้จริงฉันจะอัปเดต แต่สำหรับตอนนี้ก็เพียงพอแล้วที่จะให้ความรู้สึกอบอุ่นเป็นฝอยที่รู้ว่ามันเป็นไปได้ในทางทฤษฎี
Ryan C. Thompson

2

ฉันใช้งานสคริปต์เพื่อทำสิ่งนี้ คุณสามารถรับได้ที่นี่: https://github.com/DarwinAwardWinner/screen-sendenv

หลังจากใส่screen-sendenv.pyลงในของ$PATHคุณคุณสามารถใช้ตัวอย่างต่อไปนี้ใน. 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
}

หากต้องการใช้งานให้เรียกใช้screen_pushenvก่อนที่จะเรียกใช้screen -rการเซสชันหน้าจอของคุณอีกครั้ง จากนั้นหลังจากที่ติดกับคุณสามารถปรับปรุงสภาพแวดล้อมในเปลือกหอยที่มีอยู่กับscreen -r screen_pullenvฟังก์ชั่น tmux ทำสิ่งเดียวกันให้ได้สำหรับ tmux ซึ่งเป็นเทอร์มินัลมัลติเพล็กเซอร์อื่น ๆ


Wow Ryan นั่นเป็นรหัสจำนวนมาก เกิดอะไรขึ้นกับคำตอบที่ยอมรับก่อนหน้านี้ (อย่างน้อยก็เป็นแรงบันดาลใจ)
Benjamin Bannier

1
ฉันพบว่าหน้าจอ (และ tmux) มีคำสั่ง "setenv" ที่ตั้งค่าตัวแปรสภาพแวดล้อมสำหรับหน้าจอเองไม่ใช่เชลล์ในหน้าต่างปัจจุบันของหน้าจอ ดังนั้นหมายความว่าหลังจากคุณใช้สคริปต์ของฉันหน้าต่างที่สร้างขึ้นใหม่ทั้งหมดในเซสชันหน้าจอนั้นจะได้รับสภาพแวดล้อมใหม่โดยอัตโนมัติโดยไม่ต้องเรียกใช้สคริปต์อัปเดตในทุก ๆ หน้าต่าง แน่นอนว่าสคริปต์การอัปเดตยังคงมีประโยชน์สำหรับการอัปเดตเชลล์ที่มีอยู่ แต่คุณต้องเขียนมันใหม่ไม่ให้อ่านจาก FIFO แต่ต้องสืบค้นเซสชัน / หน้าจอ tmux เพื่อรับค่าใหม่
Ryan C. Thompson

คุณสามารถดูวิธีการดึงตัวแปรเข้าสู่เชลล์ปัจจุบันจากหน้าจอ / tmux เซสชันได้ที่นี่ในscreen_updateและtmux_updateฟังก์ชั่น ฉันจะอัปเดตคำตอบของฉันด้วยเวอร์ชันที่เป็นอิสระจากสิ่งเหล่านี้
Ryan C. Thompson

1
อย่างไรก็ตามเพื่อตอบคำถามของคุณโดยตรงเกี่ยวกับสิ่งที่ผิดคำตอบของคุณไม่ได้ตอบคำถาม แต่ค่อนข้างจะตอบคำถามที่เกี่ยวข้อง คุณแสดงวิธีอัปเดตตัวแปรสภาพแวดล้อมภายในเชลล์ที่ทำงานภายในเซสชันหน้าจอ แต่ไม่ใช่วิธีอัปเดตตัวแปรสภาพแวดล้อมในเซสชันของหน้าจอเอง (เช่นหน้าต่างที่เพิ่งวางไข่ใหม่สืบทอดค่าใหม่) ผมยอมรับมันได้ตลอดเวลาเพราะมันก็ยังคงเป็นทางออกที่ดี แต่ผมตั้งใจจะไปในที่สุดก็ใช้คำตอบที่แท้จริงให้กับคำถามของฉันเป็นถาม ดังนั้นไม่มีอะไรเป็นส่วนตัว
Ryan C. Thompson

เฮ้ไรอันขอบคุณที่ตอบ ตอนนี้คุณพูดsetenvแล้วฉันเห็นว่ามันดีกว่า ไม่ชัดเจนจากรหัสที่คุณเชื่อมโยง ขอบคุณอีกครั้ง!
Benjamin Bannier

2

คุณสามารถเรียกใช้setenvคำสั่งเพื่อเปลี่ยนตัวแปรสภาพแวดล้อมในกระบวนการหน้าจอแบบโต้ตอบโดยใช้: Ctrl- A+ :setenv(หมายเหตุ:อักขระเพื่อป้อนคำสั่งหน้าจอ) คุณจะได้รับพร้อมท์สำหรับชื่อและค่าตัวแปรสภาพแวดล้อม

โปรดทราบว่า (ตามคำตอบ / ความคิดเห็นอื่น ๆ ) สิ่งนี้มีผลต่อกระบวนการหน้าจอ (หลัก) ดังนั้นเซสชันหน้าจอที่สร้างขึ้นใหม่ แต่ไม่ใช่เซสชันหน้าจอปัจจุบันของคุณหรือเซสชันหน้าจอใด ๆ ที่มีอยู่

คุณสามารถระบุชื่อตัวแปรสภาพแวดล้อมและความคุ้มค่าในเวลาเดียวกันถ้าคุณต้องการ: -Ctrl + จะตั้งค่า DISPLAY เป็น ": 100" สำหรับเซสชันหน้าจอใหม่A:setenv DISPLAY :100

ในการลบตัวแปรสภาพแวดล้อมคุณสามารถใช้ 'unsetenv' - เช่นCtrl- A+:unsetenv DISPLAY


0

นี่อาจเป็นวิธีที่ง่ายกว่า (คุณตัดสินใจ) ส่วนที่สำคัญคือนามแฝงที่เรียกใช้savedisplayฟังก์ชันทุกครั้งที่screenเรียกใช้คำสั่ง คำสั่งจะไม่ทำงานโดยอัตโนมัติจึงสามารถใส่ในแทนสิ่งที่พิเศษมากเช่น~/.bashrc~/.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'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.