Mengapa sh (bukan bash) mengeluh tentang fungsi yang didefinisikan dalam .bashrc saya?

11

Saya mendapatkan yang ini ketika saya membuka sesi terminal:

sh: error mengimpor definisi fungsi untuk `read.json '

sh: error mengimpor definisi fungsi untuk `ts-project '

sh tidak menyukai fungsi-fungsi ini karena terlihat seperti:

read.json(){
   ::
}

dan

ts-project(){
   ::
}

pertanyaan sebenarnya adalah - mengapa shmenyentuh / menafsirkan file-file ini? Saya menggunakan MacOS dan melihat ini sebelumnya, ini adalah misteri. Saya pikir hanya bash yang akan memuat file-file ini.

perbarui : bash dan sh tidak ada yang luar biasa. ketika saya mengetik bash ke terminal, saya mendapatkan ini:

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

ketika saya mengetik shdi terminal, saya mendapatkan ini:

alex$ sh
sh: error importing function definition for `read.json'
sh: error importing function definition for `ts-project'
sh-3.2$ 
Alexander Mills
sumber
1
Mungkin / bin / sh adalah bash pada sistem itu?
Jeff Schaller
1
tak satu pun dari mereka saling sumber, saya menemukan itu adalah praktik yang buruk dengan cara yang sulit. Namun, ~ / .profile mencari sumber file bash bersama, jadi mungkin shapa sumber file .profile?
Alexander Mills
1
Informasi tentang memiliki file ~ / .profile yang sumber file bersama tampaknya penting bagi saya.
Jeff Schaller
3
Apa yang saya maksud dengan / bin / sh menjadi bash adalah mungkin ada symlinked atau hardlinked ke bash. Bash kemudian mengemulasi sh, tetapi juga sumber ~ / .profile. Saya hanya tidak tahu bagaimana paket OSX sh dan bash.
Jeff Schaller
3
Mereka dibangun dari bashsumber yang sama , yang satu dengan STRICT_POSIX, yang lain tanpa itu.
Mosvy

Jawaban:

20

Kesalahan itu terjadi ketika bashmenyamar sebagai shell POSIX mencoba mengimpor fungsi-fungsi dari lingkungan, bukan ketika memuatnya dengan menafsirkan file seperti ~/.bashrcatau itu. Contoh sederhana:

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

Saya berharap bashuntuk tidak memuat fungsi-fungsi dari lingkungan ketika dalam mode posix, tetapi ya , dan hanya mengeluh ketika nama mereka mengandung karakter lucu.

Perhatikan bahwa bashjuga akan berjalan dalam modus POSIX ketika POSIXLY_CORRECTatau POSIX_PEDANTICvariabel lingkungan diatur, atau ketika dikompilasi dengan --enable-strict-posix-default/ STRICT_POSIX.

Yang terakhir ini tampaknya menjadi kasus untuk /bin/shdi MacOS (lihat di sini untuk PRODUCT_NAME = sh), di mana saya berharap kesalahan ini juga memicu ketika menggunakan fungsi perpustakaan seperti popen(3)atau system(3).

mosvy
sumber
3
Cara mengatasinya: jangan ekspor fungsi di lingkungan. Ini adalah fitur anti bash yang menyebabkan (atau lebih tepatnya, hanya) Shellshock dan seharusnya dihapus, tetapi bukan karena orang bodoh menggunakannya. Jangan menjadi salah satu dari mereka.
R .. GitHub BERHENTI MEMBANTU ICE
Fakta bahwa bash mengimpor fungsi bahkan ketika dipanggil shadalah apa yang membuat kerentanan shellshock / bashdoor jauh lebih buruk.
Stéphane Chazelas
Lihat juga SHELLOPTS=posixdan -o posixuntuk cara-cara lain untuk mengaktifkan mode posix.
Stéphane Chazelas
Perhatikan juga bahwa set -a/ set -o allexportjuga menyebabkan bash untuk mengekspor semua fungsi (dan jika dipanggil sebagai sh, menyebabkan POSIXLY_CORRECTdisetel dan diekspor!)
Stéphane Chazelas
( sh -amenyebabkan POSIXLY_CORRECTdiatur dan diekspor; set -asetelah shtanpa -adimulai tidak mengekspor POSIXLY_CORRECTkarena diatur sebelum -adiberlakukan).
Stéphane Chazelas
5

Untuk menjawab bagian tentang mengapa read.jsondan ts-projectbukan nama fungsi portabel:

Menurut POSIX, definisi fungsi harus dinamai oleh

sebuah kata yang hanya terdiri dari garis bawah, angka, dan alfabet dari set karakter portabel. Karakter pertama dari sebuah nama bukan digit.

Juga dikenal sebagai pengidentifikasi , dalam bahasa C. Atau di regex:[_a-zA-Z][0-9_a-zA-Z]*

pengguna2394284
sumber
Tetapi POSIX tidak melarang implementasi menerima nama lain untuk fungsi, jadi bash tidak harus memaksakan pembatasan tersebut ketika dalam mode POSIX. nama fungsi berbagi namespace yang sama dengan argumen perintah, jadi tidak ada alasan untuk menerima apa pun (seperti zsh/ rc/ fish...)
Stéphane Chazelas
@ StéphaneChazelas: Saya tahu, tetapi apa artinya berada dalam mode POSIX, jika tidak "menumpahkan semua ekstensi", seperti pada "tidak menerimanya secara diam-diam"?
user2394284
@ user2394284 tentu tidak berarti bahwa dalam bash, atau itu tidak akan mengimpor fungsi dari lingkungan saat dalam mode POSIX, yang tidak diperlukan oleh spesifikasi POSIX ;-)
mosvy
@ Mosvy: Ya, terbukti bahwa bash gagal di suatu tempat di sepanjang jalan - saya akan mengatakan menjadi shell POSIX biasa, yang akan menjadi bug.
user2394284
0

Jadi apa yang menyebabkannya adalah saya mencari beberapa skrip bash di file ~ / .bashrc saya seperti ini:

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

jadi saya hanya mengubahnya menjadi:

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

jadi secara teori jika itu dipanggil shmaka tidak akan mencoba untuk sumber file-file itu, tetapi tidak yakin apakah ini berfungsi 100% dari waktu.

Alexander Mills
sumber