ทำไม sh (ไม่ใช่ทุบตี) บ่นเกี่ยวกับฟังก์ชั่นที่กำหนดไว้ใน. bashrc ของฉัน


11

ฉันได้รับสิ่งนี้เมื่อฉันเปิดเซสชันเทอร์มินัล:

sh: ข้อผิดพลาดการนำเข้าคำจำกัดความของฟังก์ชั่นสำหรับ `read.json '

sh: ข้อผิดพลาดการนำเข้าคำจำกัดความของฟังก์ชั่นสำหรับ `ts-project '

sh ไม่ชอบฟังก์ชั่นเหล่านี้เพราะมันดูเหมือน:

read.json(){
   ::
}

และ

ts-project(){
   ::
}

คำถามที่แท้จริงคือ - ทำไมการshสัมผัส / ตีความไฟล์เหล่านี้? ฉันใช้ MacOS และเห็นสิ่งนี้มาก่อนมันเป็นเรื่องลึกลับ ฉันคิดว่าทุบตีเท่านั้นที่จะโหลดไฟล์เหล่านี้

update : ทุบตีและ sh จะไม่มีอะไรผิดปกติ เมื่อฉันพิมพ์ bash ในเทอร์มินัลฉันได้รับสิ่งนี้:

alex$ bash
beginning to load .bashrc
finished loading .bashrc
bash-3.2$ 

เมื่อฉันพิมพ์shใน terminal ฉันได้รับสิ่งนี้:

alex$ sh
sh: error importing function definition for `read.json'
sh: error importing function definition for `ts-project'
sh-3.2$ 

1
บางที / bin / sh กำลัง bash ในระบบนั้น
Jeff Schaller

1
ไม่มีใครมาหากันฉันค้นพบว่ามันเป็นการฝึกฝนที่ไม่ดีอย่างหนัก อย่างไรก็ตาม ~ / .profile กำลังหาไฟล์ bash ที่ใช้ร่วมกันดังนั้นอาจshเป็นแหล่งที่มาของไฟล์. profile
Alexander Mills

1
ข้อมูลเกี่ยวกับการมีไฟล์ ~ / .profile ที่แหล่งไฟล์ที่แชร์นั้นสำคัญสำหรับฉัน
Jeff Schaller

3
สิ่งที่ฉันหมายถึงโดย / bin / sh ถูกทุบตีเป็นไปได้ว่ามันเป็น symlinked หรือ hardlinked เพื่อทุบตี จากนั้นทุบตีเลียนแบบ sh แต่ยังแหล่ง ~ / .profile ฉันไม่รู้ว่าแพกเกจ OSX นั้นน่ากลัวและดุดันอย่างไร
Jeff Schaller

3
พวกเขากำลังสร้างจากbashแหล่งเดียวกันแหล่งหนึ่งที่มีอีกแหล่งหนึ่งSTRICT_POSIXโดยไม่มีมัน
mosvy

คำตอบ:


20

ข้อผิดพลาดนั้นเกิดขึ้นเมื่อทำการbashปลอมแปลงเป็นเชลล์ POSIX พยายามที่จะนำเข้าฟังก์ชั่นเหล่านั้นจากสภาพแวดล้อมไม่ใช่เมื่อทำการโหลดโดยการตีความไฟล์เช่น~/.bashrcหรือเช่นนั้น ตัวอย่างที่ง่าย:

foo.bar(){ true; }; export -f foo.bar; bash --posix -c true
bash: error importing function definition for `foo.bar'

ฉันคาดหวังว่าจะbashไม่โหลดฟังก์ชั่นจากสภาพแวดล้อมเมื่ออยู่ในโหมด posix แต่ทำได้และจะบ่นเมื่อชื่อของพวกเขามีตัวละครตลก

ขอให้สังเกตว่าbashยังจะทำงานในโหมด POSIX เมื่อPOSIXLY_CORRECTหรือPOSIX_PEDANTICตัวแปรสภาพแวดล้อมมีการตั้งค่าหรือเมื่อมันถูกคอมไพล์ด้วย/--enable-strict-posix-defaultSTRICT_POSIX

หลังนี้ดูเหมือนว่าจะเป็นกรณีสำหรับ/bin/shบน MacOS (ดูที่นี่สำหรับPRODUCT_NAME = sh) ซึ่งผมคาดว่าข้อผิดพลาดนี้ยังทริกเกอร์เมื่อใช้ฟังก์ชั่นเช่นห้องสมุดหรือpopen(3)system(3)


3
การแก้ไข: อย่าส่งออกฟังก์ชั่นในสภาพแวดล้อม มันเป็นคุณสมบัติต่อต้านการทุบตีที่นำไปสู่ ​​(หรือเพียงแค่เป็น) Shellshock และควรถูกลบออก แต่ไม่ใช่เพราะคนโง่ใช้มัน อย่าเป็นหนึ่งในนั้น
. GitHub หยุดช่วยน้ำแข็ง

ความจริงที่ว่าทุบตีนำเข้าฟังก์ชั่นแม้ในขณะที่ถูกเรียกว่าเป็นshสิ่งที่ทำให้ shellshock / bashdoor มีความเสี่ยงมากยิ่งขึ้น
Stéphane Chazelas

ดูเพิ่มเติมSHELLOPTS=posixและ-o posixวิธีอื่น ๆ ในการเปิดใช้งานโหมด posix
Stéphane Chazelas

นอกจากนี้โปรดทราบว่าset -a/ set -o allexportยังทำให้ bash ส่งออกฟังก์ชันทั้งหมด (และหากเรียกใช้เป็นshสาเหตุPOSIXLY_CORRECTจะต้องถูกตั้งค่าและส่งออก!)
Stéphane Chazelas

( sh -aสาเหตุPOSIXLY_CORRECTที่ต้องตั้งค่าและส่งออกset -aหลังจากshไม่มี-aการเริ่มต้นจะไม่ส่งออกPOSIXLY_CORRECTเนื่องจากถูกตั้งค่าก่อนที่จะ-aมีผล)
Stéphane Chazelas

5

ในการตอบคำถามเกี่ยวกับสาเหตุread.jsonและts-projectไม่ใช่ชื่อฟังก์ชันพกพา:

ตาม POSIX นิยามฟังก์ชันต้องถูกตั้งชื่อโดย

คำที่ประกอบด้วยขีดล่างตัวเลขและตัวอักษรจากชุดอักขระแบบพกพาเท่านั้น อักขระตัวแรกของชื่อไม่ใช่ตัวเลข

หรือที่รู้จักในชื่อตัวบ่งชี้ใน C lingo หรือใน regex:[_a-zA-Z][0-9_a-zA-Z]*


แต่ POSIX ไม่ห้ามการใช้งานจากการยอมรับชื่ออื่น ๆ สำหรับฟังก์ชั่นดังนั้นทุบตีไม่จำเป็นต้องกำหนดข้อ จำกัด เหล่านั้นเมื่ออยู่ในโหมด POSIX ชื่อฟังก์ชั่นแสดงความ namespace เดียวกันเป็นข้อโต้แย้งคำสั่งเพื่อให้มีเหตุผลที่จะยอมรับเพียงแค่ไม่มีอะไร (เช่นzsh/ rc/ fish... )
Stéphane Chazelas

@ StéphaneChazelas: ฉันรู้ แต่มันหมายความว่าอะไรในโหมด POSIX ถ้าไม่ใช่ "ส่วนขยายทั้งหมด" ในขณะที่ "ไม่ยอมรับอย่างเงียบ ๆ "
user2394284

@ user2394284 แน่นอนไม่ได้หมายความว่าในbashหรือจะไม่นำเข้าฟังก์ชั่นจากสภาพแวดล้อมในขณะที่อยู่ในโหมด POSIX ซึ่งไม่จำเป็นต้องใช้โดย POSIX spec ;-) #
38819

@mosvy: ใช่มันเห็นได้ชัดว่าทุบตีล้มเหลวที่ไหนสักแห่งระหว่างทาง - ฉันจะบอกว่าเป็นเปลือก POSIX ธรรมดาซึ่งจะเป็นข้อผิดพลาด
user2394284

0

ดังนั้นสิ่งที่ทำให้มันเกิดขึ้นคือฉันกำลังหาสคริปต์ bash ในไฟล์ ~ / .bashrc เช่น:

for f in "$HOME/.oresoftware/bash/"*; do
   . "$f"
done;

ดังนั้นฉันเพิ่งเปลี่ยนเป็น:

for f in "$HOME/.oresoftware/bash/"*; do
  if [[ "$(basename "$0")" != 'sh' ]]; then
      # source only if not using sh
      . "$f"
  fi
done;

โดยทางทฤษฎีแล้วถ้ามันถูกเรียกใช้shมันจะไม่พยายามแหล่งที่มาของไฟล์เหล่านั้น แต่ไม่แน่ใจว่ามันใช้งานได้ 100% ของเวลาหรือไม่

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