Bagaimana menemukan file di mana fungsi bash didefinisikan?


33

Saya tidak tahu bagaimana menemukan file di mana fungsi bash didefinisikan ( __git_ps1dalam kasus saya).

Saya bereksperimen dengan declare, type, which, tapi tidak ada yang memberitahu saya file sumber. Saya membaca di suatu tempat yang declaredapat mencetak nama file dan nomor baris, tetapi tidak dijelaskan caranya. The helphalaman untuk declaretidak mengatakan itu baik.

Bagaimana saya bisa mendapatkan informasi ini?


Jika jalur ke file fungsi tidak termasuk $PATH, maka typetidak akan berfungsi. Anda mungkin ingin mencoba hanya menggunakan findatau locate. locateakan jauh lebih cepat, karena menggunakan database yang sudah ada sebelumnya, tetapi itu tidak akan berfungsi jika perintah itu diinstal baru-baru ini.
user628544

Jawaban:


37

Jika Anda siap untuk menjalankan fungsi, maka Anda bisa mendapatkan informasi dengan menggunakan set -xuntuk melacak eksekusi dan mengatur PS4variabel.

  1. Mulai bash dengan --debuggeratau gunakan shopt -s extdebuguntuk merekam info debugging tambahan.

  2. Set PS4, 'prompt' dicetak saat melacak untuk menunjukkan baris sumber.

  3. Hidupkan pelacakan.

  4. Anda kemudian dapat menjalankan fungsi Anda dan untuk setiap baris Anda akan mendapatkan nama file dari fungsi tersebut.

  5. gunakan set +xuntuk mematikan pelacakan.

Jadi untuk kasus ini Anda akan lari

bash --debugger
PS4='+ ${BASH_SOURCE[0]} '
set -x ; __git_ps1 ; set +x

"-x Setelah memperluas setiap perintah sederhana, untuk perintah, perintah kasus, pilih perintah, atau aritmatika untuk perintah, tampilkan nilai PS4 yang diperluas, diikuti dengan perintah dan argumennya yang diperluas atau daftar kata yang terkait." Bagus!
l0b0

25

Jika Anda tidak ingin menjalankan fungsinya, Anda masih dapat mengatur debugging dan mendapatkan informasi. Langkah-langkahnya adalah

  1. mulai bash --debuggeratau shopt -s extdebugsebelum fungsi didefinisikan.
  2. declare -F __git_ps1

dan itu akan melaporkan di mana fungsi didefinisikan.

Kelebihan metode ini dibandingkan dengan melihat jejak eksekusi beranotasi dengan PS4 adalah

  • Output yang jauh lebih sedikit
  • Itu langsung menjawab pertanyaan

Keuntungan dari jejak eksekusi adalah

  • Lihat semua fungsi yang dipanggil sekaligus
  • Lihat hubungan antara fungsi yang disebut
  • Lihat rekursi

Saya sangat merekomendasikan memiliki shopt -s extdebugpada awal keduanya ~/.bashrcdan ~/.bash_profileuntuk menutupi file yang berbeda yang digunakan dalam kasus Doa yang berbeda .


1
Ini juga berfungsi jika shopt -s extdebugdipanggil setelah fungsi didefinisikan. Berhati-hatilah nomor baris tidak aktif (bug saat ini) jika fungsi dinyatakan melalui eval.
Stéphane Chazelas

Saya setelah penyelesaian yang salah kaprah untuk vpnc. Setelah bash --debuggersaya harus benar-benar memicu penyelesaian untuk mendapatkan fungsi selesai didefinisikan dan melaporkannya dari declare -F _vpnc.
Harald

9

@ icarus solusi hebat bekerja untuk fungsi, selama mereka didefinisikan secara harfiah dan bukan hasil dari evalisi file lain (di mana file dengan evalakan muncul sebagai sumber). Itu tidak akan mencetak file sumber alias, built-in shell (seperti echo) dan executable (biner atau tidak), dan saya percaya informasi ini tidak tersedia secara umum. Beberapa perintah mungkin mencetak file sumber mereka (dan bahkan mungkin benar tentang hal itu), baik dalam pelaksanaan normal atau sebagai respons terhadap sinyal.

__git_ps1didefinisikan dalam /usr/share/git/git-prompt.shdan /usr/share/git/completion/git-prompt.shdi sistem saya, Arch Linux, jadi mungkin sama untuk Anda.

Silahkan lihat di Invocation bagian man bashjika Anda ingin mencari perintah khusus yang bersumber pada awal shell - mereka mungkin sumber file lainnya yang pada gilirannya sumber file lainnya.


Bisakah seseorang mendapatkan daftar file yang bersumber saat memulai bash?
pfnuesel

@ pfnuesel - terserah Anda. Defaultnya adalah dalam $HOME/.bashrcdan dalam $HOME/.profile. Lihat: linuxfromscratch.org/blfs/view/svn/postlfs/profile.html yang menjelaskan beberapa detail kapan dan bagaimana masing-masing file berasal.
Joe

2
@ Jo gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html adalah referensi yang jauh lebih baik. /etc/profile, $HOME/.bash_profile, $HOME/.bash_login, Dan isi $ENVdan $BASH_ENVperlu ditambahkan ke daftar Anda.
icarus

@icarus - Terima kasih. Itu penjelasan yang lebih baik.
Joe

8

Tampaknya tidak mungkin dilakukan bash, tetapi ada di zsh:

$ type __git_ps1
> __git_ps1 is a shell function from /usr/share/git/git-prompt.sh

Pertanyaannya tidak menentukan bash ...
Jeff Schaller

4
@JeffSchaller: Cara yang jelas untuk menggunakan jawaban ini adalah dengan mengatur zsh untuk mencari file yang sama dengan yang akan dilakukan bash, kemudian menggunakannya untuk menemukan definisi. Jawaban ini tidak menyarankan beralih ke zsh, hanya saja itu jelas alat yang berguna yang memahami sintaksis shell lebih baik daripada alat generik seperti find/ locate/ grep.
Peter Cordes

Saya akan mengklaim, @PeterCordes, bahwa jawaban ini saat ini tidak melakukan apa yang Anda katakan harus dilakukan untuk menjawab Pertanyaan. Saya tidak tahu apakah zsh secara asli membaca file yang sama dengan bash.
Jeff Schaller

@JeffSchaller: Setuju jawaban ini membutuhkan perbaikan. zsh hampir pasti tidak membaca ~/.whateverfile yang sama dengan bash secara default, dan hanya akan memberikan jawaban yang berguna untuk fungsi yang didefinisikan di lokasi bersama seperti dalam kasus ini, yang tidak didefinisikan ulang ~/.bashrcatau apa pun.
Peter Cordes

-1

Deklarasikan fungsi dengan nama yang sama dan atur agar dibaca hanya sedini mungkin, kemudian aktifkan mode xtrace, seperti:

__git_ps1(){ :;}
readonly -f __git_ps1
set -x

Setelah itu ketika Anda masuk Anda akan melihat jejak informasi yang mencakup sumber file. Saat ini ada upaya untuk deklarasi fungsi readonly yang ada, Anda akan melihat pesan kesalahan. File sumber terakhir sebelum itu harus berisi deklarasi yang Anda cari.

Anda mungkin perlu memasukkan ini ke profil bash sistem. Ingat juga untuk mengembalikan perubahan setelah menemukan pelakunya.


-3

Apakah kamu mencoba ini?

grep -rnw '/path/to/somewhere/' -e "pattern" 

atau perintah lain yang ditemukan di sini:

Bagaimana cara menemukan semua file yang mengandung teks tertentu di Linux? | Stack Overflow

Sepertinya saya perlu memberi Anda lebih banyak penjelasan. Pertanyaan Anda bertanya "" Jadi, jika Anda menjalankan perintah berikut, ia akan mengembalikan semua file di mana fungsi bash didefinisikan.

grep -rnw 'Path2Search' -e "#!/bin/bash"

Pemrograman BASH - Fungsi | Proyek Dokumentasi Linux


1
Hanya tautan jawaban yang sama sekali tidak dianjurkan. Silakan tambahkan beberapa penjelasan.
heemayl
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.