Lihat kode:
#!/bin/bash
read -p "Eneter 1 for UID and 2 for LOGNAME" choice
if [ $choice -eq 1 ]
then
read -p "Enter UID: " uid
logname=`cat /etc/passwd | grep $uid | cut -f1 -d:`
else
read -p "Enter Logname: " logname
fi
not=`ps -au$logname | grep -c bash`
echo "The number of terminals opened by $logname are $not"
Kode ini digunakan untuk mengetahui jumlah terminal yang dibuka oleh pengguna pada PC yang sama. Sekarang ada dua pengguna yang masuk, misalkan x dan y. Saya saat ini login sebagai y dan ada 3 terminal terbuka di pengguna x. Jika saya menjalankan kode ini di y menggunakan cara yang berbeda seperti yang disebutkan di atas hasilnya adalah:
$ ./file.sh
The number of terminals opened by x are 3
$ bash file.sh
The number of terminals opened by x are 5
$ sh file.sh
The number of terminals opened by x are 3
$ source file.sh
The number of terminals opened by x are 4
$ . ./file.sh
The number of terminals opened by x are 4
Catatan: Saya melewati 1 dan 1000 uid untuk semua executable ini.
Sekarang bisakah Anda menjelaskan perbedaan di antara semua ini?
command-line
bash
scripts
Ramana Reddy
sumber
sumber
Jawaban:
Satu-satunya perbedaan utama adalah antara sumber dan pelaksanaan skrip.
source foo.sh
akan sumber itu dan semua contoh lain yang Anda tunjukkan mengeksekusi. Lebih detail:./file.sh
Ini akan menjalankan skrip bernama
file.sh
yang ada di direktori saat ini (./
). Biasanya, ketika Anda menjalankancommand
, shell akan melihat direktori di dalam Anda$PATH
untuk file executable yang disebutcommand
. Jika Anda memberikan path lengkap, seperti/usr/bin/command
atau./command
, maka$PATH
diabaikan dan file tertentu dijalankan.../file.sh
Ini pada dasarnya sama dengan
./file.sh
kecuali bahwa alih-alih mencari di direktori saat ini untukfile.sh
, itu mencari di direktori induk (../
).sh file.sh
Ini setara dengan
sh ./file.sh
, seperti di atas akan menjalankan skrip yang disebutfile.sh
dalam direktori saat ini. Perbedaannya adalah Anda menjalankannya secara eksplisit dengansh
shell. Pada sistem Ubuntu, itudash
dan tidakbash
. Biasanya, skrip memiliki garis shebang yang memberikan program yang seharusnya dijalankan. Memanggil mereka dengan yang berbeda akan menimpanya. Sebagai contoh:Script itu hanya akan mencetak nama shell yang digunakan untuk menjalankannya. Mari kita lihat apa yang dikembalikan ketika dipanggil dengan cara yang berbeda:
Jadi, panggilan memanggil skrip dengan
shell script
akan menimpa garis shebang (jika ada) dan menjalankan skrip dengan shell apa pun yang Anda katakan.source file.sh
atau. file.sh
Ini disebut, cukup mengejutkan, sumber skrip. Kata kunci
source
adalah alias untuk.
perintah builtin shell . Ini adalah cara menjalankan skrip di dalam shell saat ini. Biasanya, ketika sebuah skrip dieksekusi, ia dijalankan di dalam cangkangnya sendiri yang berbeda dari yang sekarang. Menggambarkan:Sekarang, jika saya mengatur variabel
foo
ke sesuatu yang lain di shell induk dan kemudian menjalankan skrip, skrip akan mencetak nilai yang berbeda darifoo
(karena itu juga diatur dalam skrip) tetapi nilaifoo
di dalam shell induk tidak akan berubah:Namun, jika saya sumber skrip alih-alih menjalankannya, skrip akan dijalankan di shell yang sama sehingga nilai
foo
di dalam induk akan diubah:Jadi, sumber digunakan dalam beberapa kasus di mana Anda ingin skrip memengaruhi shell tempat Anda menjalankannya. Ini biasanya digunakan untuk mendefinisikan variabel shell dan membuatnya tersedia setelah skrip selesai.
Dengan semua itu dalam pikiran, alasan Anda mendapatkan jawaban yang berbeda adalah, pertama-tama, bahwa skrip Anda tidak melakukan apa yang Anda pikirkan. Ini menghitung berapa kali yang
bash
muncul di outputps
. Ini bukan jumlah terminal terbuka , ini adalah jumlah cangkang yang berjalan (pada kenyataannya, bahkan bukan itu, tapi itu diskusi lain). Untuk memperjelas, saya sedikit menyederhanakan skrip Anda untuk ini:Dan jalankan dengan berbagai cara hanya dengan satu terminal terbuka:
Peluncuran langsung
./foo.sh
,.Di sini, Anda menggunakan garis shebang. Ini berarti bahwa skrip dijalankan secara langsung oleh apa pun yang diatur di sana. Ini mempengaruhi cara skrip ditampilkan dalam output dari
ps
. Alih-alih terdaftar sebagaibash foo.sh
, itu hanya akan ditampilkan sebagaifoo.sh
yang berarti bahwa Andagrep
akan melewatkannya. Sebenarnya ada 3 instance bash yang berjalan: proses induk, bash menjalankan skrip dan yang lainnya menjalankanps
perintah . Yang terakhir ini penting, meluncurkan perintah dengan substitusi perintah (`command`
atau$(command)
) menghasilkan salinan shell induk yang diluncurkan dan menjalankan perintah. Di sini, bagaimanapun, tidak ada yang ditampilkan karena cara yangps
menunjukkan hasilnya.Peluncuran langsung dengan shell eksplisit (bash)
Di sini, karena Anda menjalankan
bash foo.sh
, output darips
akan ditampilkanbash foo.sh
dan dihitung. Jadi, di sini kita memiliki proses induk,bash
skrip yang berjalan, dan shell kloning (running theps
) semua ditampilkan karena sekarangps
akan menampilkan masing-masing karena perintah Anda akan memasukkan katabash
.Peluncuran langsung dengan shell yang berbeda (
sh
)Ini berbeda karena Anda menjalankan skrip dengan
sh
dan tidakbash
. Karena itu, satu-satunyabash
contoh adalah shell induk tempat Anda meluncurkan skrip Anda. Semua shell lain yang disebutkan di atas dijalankan olehsh
sebagai gantinya.Sumber (baik dengan
.
atausource
, hal yang sama)Seperti yang saya jelaskan di atas, sumber skrip membuatnya berjalan di shell yang sama dengan proses induk. Namun, subkulit terpisah mulai meluncurkan
ps
perintah dan itu menjadikan total menjadi dua.Sebagai catatan terakhir, cara yang benar untuk menghitung proses yang sedang berjalan bukan untuk menguraikan
ps
tetapi untuk digunakanpgrep
. Semua masalah ini akan dihindari seandainya Anda baru saja berlariJadi, versi skrip Anda yang selalu mencetak angka yang tepat adalah (perhatikan tidak adanya substitusi perintah):
Itu akan mengembalikan 1 ketika bersumber dan 2 (karena bash baru akan diluncurkan untuk menjalankan skrip) untuk semua cara lain peluncuran. Itu masih akan mengembalikan 1 ketika diluncurkan dengan
sh
karena proses anak tidakbash
.sumber
./foo.sh
berjalan di shell baru yang bukan salinan induknya. Misalnya, jika Anda mengaturfoo="bar"
di terminal Anda dan kemudian menjalankan skrip yang dijalankanecho $foo
, Anda akan mendapatkan baris kosong karena shell skrip tidak akan mewarisi nilai variabel.pgrep
adalah biner yang terpisah, dan ya dijalankan oleh skrip yang Anda jalankan.