ใช้. bashrc โดยไม่ทำลาย sftp


20

ปัญหาของฉันคือฉันต้องตั้งค่าตัวแปรไม่กี่และส่งออกไม่กี่บรรทัดทุกครั้งที่ฉันเข้าสู่เชลล์ ssh และในเวลาเดียวกันฉันต้องสามารถใช้ sftp เพื่อ tarnsfer ไฟล์ผ่าน Filezilla

ตอนนี้ตาม FAQ ของ openssh ที่http://www.openssh.org/faq.htmlหากสคริปต์เริ่มต้นของคุณดังก้องเอาท์พุทประเภทใดก็จะยุ่งกับ sftp ดังนั้นจึงเกิดความล่าช้าอย่างไม่มีกำหนดหรือเกิดข้อผิดพลาดด้วย "การเชื่อมต่อถูกปิดโดยเซิร์ฟเวอร์ด้วยรหัสออก 128"

ฉันลองใช้วิธีแก้ไขปัญหาเช่นย้าย. bashrc ไปยัง. bash_profile หรือใช้รหัสต่อไปนี้ใน. bashrc:

if [ "$TERM" != "dumb" ]
then
   source .bashc_real
fi

และ:

if [ "$TERM" = "xterm" ]
then
   source .bashc_real
fi

อย่างไรก็ตามไม่มีอะไรทำงาน เทอร์มินัลเชลล์ของฉันคือทุบตีและฉันเชื่อมต่อกับ sftp ด้วย filezilla

คำตอบ:



17

คำตอบของไมค์น่าจะใช้ได้ แต่มันก็คุ้มค่าที่จะชี้ให้เห็นว่าคุณสามารถทำสิ่งนี้ได้อย่างระมัดระวังโดยเลือกไฟล์เริ่มต้นที่จะนำข้อมูล verbose มาจากหน้า bash man:

เมื่อ bash ถูกเรียกใช้เป็นเชลล์ล็อกอินแบบโต้ตอบหรือเป็นเชลล์ที่ไม่มีการโต้ตอบกับตัวเลือก --login มันจะอ่านและเรียกใช้คำสั่งจากไฟล์ / etc / profile ก่อนหากไฟล์นั้นมีอยู่ หลังจากอ่านไฟล์นั้นจะค้นหา ~ / .bash_profile, ~ / .bash_login และ ~ / .profile ตามลำดับและอ่านและเรียกใช้คำสั่งจากไฟล์แรกที่มีอยู่และอ่านได้ ตัวเลือก --noprofile อาจถูกใช้เมื่อเชลล์เริ่มต้นเพื่อยับยั้งพฤติกรรมนี้

เมื่อเชลล์เชิงโต้ตอบที่ไม่ใช่เชลล์ล็อกอินเริ่มทำงาน bash จะอ่านและดำเนินการคำสั่งจาก ~ / .bashrc หากไฟล์นั้นมีอยู่ สิ่งนี้อาจถูกยับยั้งโดยใช้ตัวเลือก --norc ตัวเลือกไฟล์ --rcfile จะบังคับให้ทุบตีเพื่ออ่านและดำเนินการคำสั่งจากไฟล์แทน ~ / .bashrc

เครื่องมือ sftp / scp เริ่มต้นเชลล์ที่ไม่ใช่การเข้าสู่ระบบแบบโต้ตอบดังนั้น. bashrc จะได้รับแหล่งที่มา หลายแหล่งที่มา. bashrc จาก. bash_profile หรือกลับกันดังนั้นมันอาจทำให้สับสนได้ เคล็ดลับที่ดีสำหรับการทดสอบความสะอาดของสภาพแวดล้อมการเข้าสู่ระบบของคุณคือการ ssh ด้วยคำสั่งซึ่งจำลองแบบเดียวกับการเชื่อมต่อ scp / sftp ตัวอย่างเช่น: ssh myhost /bin/trueจะแสดงสิ่งที่ scp / sftp เห็นเมื่อพวกเขาเชื่อมต่อ

ตัวอย่างง่ายๆ:

insyte@mazer:~$ echo "echo Hello from .profile" > .profile
insyte@mazer:~$ echo "echo Hello from .bashrc" > .bashrc

sazerac:~ insyte$ ssh mazer /bin/true
Hello from .bashrc
sazerac:~ insyte$

insyte@mazer:~$ rm .bashrc

sazerac:~ insyte$ ssh mazer /bin/true
sazerac:~ insyte$

การทดสอบครั้งแรกจะทำให้ scp / sftp / rsync เป็นต้นแตก รุ่นที่สองจะทำงานได้ดี


ฉันไม่เห็นด้วยว่า"เครื่องมือ sftp / scp เริ่มต้นเชลล์ที่ไม่ใช่การเข้าสู่ระบบแบบโต้ตอบ "เนื่องจากเราไม่สามารถโต้ตอบกับเชลล์ได้ แต่ผมไม่เข้าใจว่าทำไม.bashrcจะ source'd สำหรับหรือscp ssh host command
pynexj

2
คำว่า "โต้ตอบ" ไม่ได้เป็นอัตวิสัย เป็นคำที่ใช้โดย bash เพื่ออธิบายหนึ่งในโหมดเริ่มต้นของมัน มันเป็นความจริงที่ sftp / scp เริ่มต้น "เชลล์ที่ไม่ใช่การเข้าสู่ระบบแบบโต้ตอบ" อย่าลังเลที่จะโต้แย้งกับนักพัฒนาว่าการไม่จัดหา. bashrc นั้นเหมาะสมในกรณีนี้หรือไม่ ฉันแค่บอกคุณว่ามันทำอะไร
Insyte

2
Bashเรียกโดยscpหรือssh host commandเป็นจริงไม่ใช่แบบโต้ตอบ ฉันเพิ่งพบสิ่งนี้ในคู่มือทุบตี: "ทุบตีพยายามที่จะตรวจสอบเมื่อมันถูกเรียกใช้กับอินพุตมาตรฐานที่เชื่อมต่อกับการเชื่อมต่อเครือข่ายเช่นเดียวกับเมื่อดำเนินการโดยเปลือกระยะไกล daemon มักจะrshd หรือเชลล์ปลอดภัย daemon sshdถ้าทุบตีกำหนด มันกำลังถูกเรียกใช้ในลักษณะนี้มันจะอ่านและดำเนินการคำสั่งจาก ~/.bashrcหากไฟล์นั้นมีอยู่และอ่านได้ " นี่คือประวัติที่น่าสนใจ
pynexj

1
นอกจากนี้ยังดูในส่วนการเข้าสู่ระบบแบบโต้ตอบหอยระยะไกลที่ไม่ใช่ไม่ใช่ในหน้านี้วิกิพีเดีย
pynexj

3

หากคุณใช้ csh:

if ($?prompt)
  ... interactive stuff ...

และถ้ามันทุบตี:

if [[ $- == *i* ]]; then
  ... interactive stuff ...
fi

หรืออีกทางเลือกหนึ่งโดยใช้นิพจน์ทั่วไปของ bash:

if [[ $- =~ i ]]; then
  ... interactive stuff ...
fi

บรรทัดเหล่านี้ควรอยู่ก่อนหน้าบรรทัดที่คุณ ouput / echo บางอย่างกลับมา


สวัสดีคุณช่วยอธิบายรหัสได้ไหม ฉันรู้ว่า $? เป็นระดับการส่งคืนของคำสั่งก่อนหน้า ฉันไม่เข้าใจคำสั่ง $? prompt และ $ - หรือเฉพาะ csh?
Joel G Mathew

1
@Droidzone: $?varในcshผลตอบแทนที่ 1 ถ้าvarมีการกำหนดและ 0 มิฉะนั้น $-ในbashจะมีiถ่านในมูลค่าถ้าเปลือกเป็นแบบโต้ตอบ
pynexj

ควรอัพเดตคำตอบเพื่ออธิบาย $ - เป็นตัวแปรพิเศษของตัวเลือกเชลล์ ดูstackoverflow.com/questions/5163144/…
maninvan

1

วิธีการแก้ปัญหาของไมค์ก็ใช้ได้สำหรับฉันเช่นกัน แต่เนื่องจากเชลล์เริ่มต้นของฉันคือ TCSH ฉันจึงต้องแก้ไขการแก้ไขเล็กน้อยดังนี้ (ใน. tcshrc):

if ( $?SSH_TTY ) then
    exec /bin/bash
endif

แค่คิดว่าฉันจะแบ่งปันเพื่อประโยชน์ของทุกคน


0

ฉันชอบโซลูชันอื่น ๆ ที่กล่าวถึงที่นี่ดีกว่า แต่ฉันคิดว่าฉันทิ้งโซลูชันที่ฉันใช้ในปัจจุบันบน bash และ csh VMs ของฉันเพื่อป้องกันการยกเลิกการเชื่อมต่อ SFTP เนื่องจากคำสั่ง echo ในสคริปต์เริ่มทำงานของฉันในกรณีที่ใคร ๆ .

ใน BASH:

if [ $TERM == "xterm" ] || [ $TERM == "xterm-256color" ]; then
  echo "Xterm display identified: echo enabled"
  echo_disable="0"
else
  echo_disable="1"
fi

# Use the following for all subsequent echo commands
if [ $echo_disable == 0 ]; then
 echo "Safe to display on Xterm"
fi

ใน csh:

if ($TERM == "xterm") then
  echo "Xterm display identified: echo enabled"
  set echo_disable = "0"
else
  set echo_disable = "1"
endif

# Use the following for all subsequent echo commands
if !( "$echo_disable" ) echo "Safe to display on Xterm"

มันค่อนข้างโหดร้าย แต่ก็ใช้ได้


ฉันลองใช้รหัส ["$ SSH_TTY"] ด้านบนและพบว่ามันใช้งานได้กับโปรแกรมไคลเอนต์แบบง่ายเช่น putty เท่านั้น เมื่อฉันใช้ NoMachine มันไม่ได้ให้ผลลัพธ์ใด ๆ นี่คือเหตุผลที่ฉันต้องการรวม "xterm-256color" ในรหัสด้านบน
Bob Noonan

น่าสนใจพอที่จะใช้ "if ($? SSH_TTY)" ก็ใช้ไม่ได้กับ csh VM ของฉัน ฉันตรวจสอบและไม่มีตัวแปรสภาพแวดล้อม SSH_TTY ที่กำหนดไว้ ดังนั้นรหัสของฉันด้านบนอาจเป็นประโยชน์กับผู้อื่นที่มีสถานการณ์คล้ายกัน
Bob Noonan

0

นี่คือบรรทัดแรกของ.bashrcไฟล์(เริ่มต้น) ของฉัน:

# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

การตรวจสอบเซสชันแบบโต้ตอบหลีกเลี่ยงการสับสนกับ SCP, SFTP หรือssh remote-host commandโหมด

หากไม่มีไฟล์นี้หากไฟล์ของคุณ.bashrcใช้echoหรือพิมพ์สิ่งอื่นใน stdout คุณอาจได้รับข้อผิดพลาดประเภทนี้:

  • SFTP: Received message too long 168435779
  • SCP: protocol error: unexpected <newline>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.