ไม่สามารถแหล่ง. bashrc ได้สำเร็จจากเชลล์สคริปต์


51

โดยปกติเราสามารถซอร์ส~/.bashrcไฟล์โดยใช้คำสั่งนี้

source ~/.bashrc

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

สคริปต์ของฉัน:

#!/bin/bash
chmod a+x ~/.bashrc
source ~/.bashrc

นอกจากนี้ยังพยายาม.(dot) sourceแทน ผลลัพธ์เดียวกัน

คำตอบ:


26

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

ในทางตรงกันข้ามsourceคำสั่งจะไม่เริ่มเชลล์อินสแตนซ์ใหม่ แต่ใช้เชลล์ปัจจุบันเพื่อให้การเปลี่ยนแปลงยังคงอยู่

หากคุณต้องการให้ทางลัดในการอ่าน. bashrc ของคุณใช้ฟังก์ชั่นเชลล์หรือนามแฝงแทนเชลล์สคริปต์เช่น

alias brc='source ~/.bashrc'

ขอบคุณสำหรับการตอบกลับอย่างรวดเร็วของคุณ โซลูชันของคุณอาจใช้งานได้ แต่ฉันต้องแก้ไขไฟล์ bashrc ด้วยตนเองเพื่อบันทึกบรรทัด 'aliac brc = .... ' ฉันพยายามพัฒนา GUI เพื่อเปลี่ยนตัวแปรสภาพแวดล้อม ดังนั้นฉันไม่สามารถแก้ไขไฟล์ bashrc ของคอมพิวเตอร์เครื่องอื่นด้วยตนเอง
shantanu

1
คุณต้องทำงานsource ~/.bashrcในเชลล์ที่คุณต้องการเปลี่ยนสภาพแวดล้อม คุณไม่สามารถเปลี่ยนได้จากกระบวนการอื่น บางที (ทั่วโลก) การเพิ่มชื่อแทนนี้อาจเป็นส่วนหนึ่งของกระบวนการติดตั้ง GUI ของคุณ
Florian Diesch

1
ดังนั้นฉันจะใส่คำสั่งนามแฝงของคุณก่อนหน้านี้ในสคริปต์แล้วเรียก brc เมื่อฉันต้องการที่จะแหล่ง. bashrc ของฉันหรือฉันต้องใส่คำสั่งนามแฝงนั้นในไฟล์ที่อื่น?
user137717

สิ่งที่ฉันทำลงไปคือส่วนขยายของคำตอบของ Florian Diesch คุณสามารถใช้ชื่อแทนหลายบรรทัดได้: alias brc = 'chmod a + x ~ / .bashrc; source ~ / .bashrc 'ฉันยังค่อนข้างใหม่ดังนั้นฉันไม่แน่ใจว่านี่ถือว่าเป็น' การปฏิบัติที่ไม่ดี ' มันทำงานได้ดี
A_user_appears

13

คุณ.bashrcมักจะเริ่มต้น:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

เนื่องจากสคริปต์ของคุณไม่มีชุด PS1 (เนื่องจากไม่ได้เป็นแบบอินเทอร์แอคทีฟ) สคริปต์จะไม่รีเซ็ตเส้นทางเนื่องจากออกก่อนกำหนด เพื่อสาธิตแก้ไขสคริปต์ของคุณ:

    #!/bin/bash
    chmod a+x ~/.bashrc
    PS1='$ '
    source ~/.bashrc

นี่จะทำให้สคริปต์ของคุณทำงานกับสิ่งใหม่.bashrcได้ หมายเหตุ: เมื่อสคริปต์ของคุณออกไป env จะถูกตั้งค่าให้เหมือนก่อนที่จะเริ่มสคริปต์ การเปลี่ยนแปลงจะมีผลในครั้งต่อไปที่เทอร์มินัลเริ่มต้น


อย่างน้อยก็ตั้งแต่ 16.04 และอาจก่อนหน้านี้ค่าเริ่มต้นของ Ubuntu .bashrcใช้วิธีที่เชื่อถือได้มากขึ้นในการตรวจสอบว่าเชลล์เป็นแบบโต้ตอบ /etc/bash.bashrcยังคงมีการทดสอบ PS1
Zanna

12

ลอง:

exec bash

สิ่งนี้ควรโหลด ~ / .bashrc, ~ / .bash_aliases ฯลฯ


9
สิ่งนี้จะแทนที่กระบวนการทุบตีปัจจุบันด้วยกระบวนการใหม่ มันไม่สั้นกว่าหรือง่ายกว่าการใช้มากนักsourceแต่จะทำลายตัวแปรใด ๆ และผู้ใช้ตั้งค่าเอง - ซึ่งอาจหรือไม่ต้องการก็ได้
Florian Diesch

ค้างไว้ในบริบทของเชลล์สคริปต์ด้วยคำสั่งอื่น ๆ หลังจาก bashrc sourcing คุณใส่คำสั่งที่ต้องการสถานะ bash ใหม่หลังจากนั้นexec bashวิธีที่ฉันเข้าใจคำสั่งหลังจากนั้นจะยังคงอยู่ในการตั้งค่า bash เหมือนเดิมหรือไม่
tatsu

11

ฉันต้องการเติมเต็มคำตอบของ ravi :

ลักษณะการทำงานนี้เป็นลักษณะเฉพาะของ Ubuntu (และอาจเป็น distros ที่ได้รับมากที่สุด) เนื่องจาก~/.bashrcไฟล์เริ่มต้นของคุณเริ่มต้นด้วยการลัดวงจร Ubuntu 18.04 เป็นต้น

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

สิ่งนั้นจะหยุดการประเมินไฟล์ถ้ามันกำลังทำงานในเชลล์ที่ไม่มีการโต้ตอบซึ่งเป็นกรณีของสคริปต์ของคุณเนื่องจากสคริปต์ทั้งหมดจะทำงานในเชลล์ที่ไม่ต้องมีการโต้ตอบและหลังจากนั้นทุกไฟล์คุณsourceจะได้รับคุณสมบัตินี้

eval สับ

ฉันพบแฮ็กที่น่าเกลียดในการแก้ปัญหา Ubuntu โดยเฉพาะโดยใช้evalแทนsource:

eval "$(cat ~/.bashrc | tail -n +10)"

มันแค่ข้ามสองสามบรรทัดแรกและประเมินส่วนที่เหลือ~/.bashrcเพื่อให้ส่วนที่เหลือถูกประเมินและแก้ไขการดำเนินการปัจจุบัน

ระวังเป็นเลขอาถรรพ์และอาจไม่สามารถใช้งานได้กับ Ubuntu ทุกรุ่น แต่อาจเป็นทางออกที่ดีถ้าคุณสร้างสคริปต์สำหรับระบบที่รู้จักมากขึ้นหรือน้อยลง

โซลูชันที่นักเล่นอาจเกี่ยวข้องกับการใช้ regex เพื่อกำหนดเป้าหมายบิตเฉพาะที่หยุดการประเมินผล

Shebang ทางเลือก

ทางเลือกอื่นที่อาจทำงานได้ดีขึ้นในบางสถานการณ์คือการบังคับให้สคริปต์ทำงานในเชลล์แบบโต้ตอบโดยการเพิ่มการตั้งค่าสถานะในshebang :

#!/bin/bash -i

ระวังสิ่งต่าง ๆ :

  • มันเป็นวิธีปฏิบัติที่ดีกว่าที่จะใช้#!/usr/bin/env bashรูปแบบ แต่วิธีนี้คุณไม่สามารถเริ่มต้นเปลือกมีข้อโต้แย้ง
  • ใช้-iมีชุดของตัวเองของผลกระทบในหมู่พวกเขาโปรแกรมจะแจ้งให้สำหรับผู้ใช้โต้ตอบนี้มักจะไม่ได้มีไว้สำหรับสคริปต์ตัวอย่างเช่นการติดตั้งdebแพคเกจอาจหยุดสคริปต์ที่แจ้งdpkg configure
  • ผมเริ่มพยายามที่จะใช้set -iและset +iเพื่อเปิดคุณลักษณะในและนอกสถานที่ที่ฉันต้องการมัน แต่นี้ไม่ได้ทำงาน

2

ไม่มีวิธีการอื่นใดที่ใช้งานได้สำหรับฉัน [ source /path/to/filevs . ./path/to/file, alias, ฯลฯ ... ] จนกระทั่งขอบคุณกวดวิชานี้ฉันพบว่าการใช้:

#!/usr/bin/env bash shebang

แทนที่จะเป็นวิธีที่ง่ายกว่า#!/usr/bin/envให้อาร์กิวเมนต์ส่งต่อไปยังล่ามซึ่งฉันคิดว่าเป็นกุญแจสำคัญที่นี่ - ดูเอกสารนี้สำหรับข้อมูลเพิ่มเติม

ไม่ว่าในกรณีใดหากคำสั่งแหล่งที่มาในรูปแบบใด ๆ ที่ไม่ได้ผลสำหรับคุณลองตรวจสอบ Shebang ของคุณนั่นอาจเป็นปัญหา :)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.