Bagaimana cara mengulang perintah dalam skrip bash shell, tetapi tidak menjalankannya?

11

Apakah ada cara untuk menjalankan skrip shell dengan menggemakan perintah tetapi tanpa menjalankannya?

Katakanlah saya memiliki skrip yang menghapus file yang namanya disimpan dalam variabel:

#!/bin/bash
set -v
FN="filename"
rm -f ${FN}

Menambahkan set -vakan mengulangi perintah berikut sebelum eksekusi:

$ ./scr.sh
FN="filename"
rm -f ${FN}

Sekarang, saya ingin melihat alur skrip ini tanpa menghapus file. TKI, saya ingin mencegah efek apa pun pada lingkungan eksternal dan sistem file. Apakah ini mungkin?

Saya bisa membungkus semua perintah dengan echoperintah, tetapi itu melelahkan untuk skrip yang panjang.

ya
sumber
Saya bukan ahli bash-scripting, tetapi jika saya akan menulis ini dengan bahasa pemrograman lain, saya akan menyimpan semua perintah dalam sebuah array. dengan cara ini harus mudah untuk dilalui dan menjalankan perintah atau mencetak keluar.
hugo der hungrige

Jawaban:

8

Tidak ada cara untuk melangkah melalui skrip untuk melihat bagaimana itu akan dijalankan tanpa benar-benar melakukan itu. Dalam contoh Anda, tidak ada ifpernyataan atau loop. Namun dalam naskah asli, seringkali ada banyak pernyataan kondisional. Cabang mana yang akan diambil akan sering bergantung pada apa yang terjadi ketika shell menjalankan perintah sebelumnya. Jika tidak menjalankan perintah, shell tidak mungkin mengetahui output apa yang akan dihasilkannya atau apa kode pengembaliannya, yang bergantung pada cabang kondisional atau pernyataan tugas berikutnya.

Jika intinya adalah Anda ingin meneliti skrip dan tahu apa fungsinya sebelum Anda menjalankannya, itu bukan ide yang buruk. Namun secara realistis, cara terbaik untuk melakukannya adalah dengan hanya meramban file dengan lessatau viatau yang serupa.

Ditambahkan

Jika Anda sedang mengembangkan skrip dan Anda ingin melewatinya pertama kali, menguji logika tetapi tidak benar-benar melakukan kerusakan jika Anda memiliki bug, solusi yang sering saya dapat gunakan adalah dengan memodifikasi saja pernyataan yang bisa menyebabkan kerusakan dengan menempelkan echoke depan.

Ini sering bekerja dalam skrip kehidupan nyata yang khas karena (a) menghasilkan daftar item yang akan Anda iterate atau nilai yang akan Anda setel variabel sering dapat dihasilkan tanpa mengubah sistem file dan (b) biasanya cukup untuk berasumsi bahwa jika Anda menjalankan perintah, itu akan berhasil.

Nicole Hamilton
sumber
Terima kasih. Akan mengejutkan saya jika ada cara, tepatnya karena alasan yang Anda sebutkan, tapi saya memutuskan untuk mencobanya. Alasan untuk ini adalah bahwa saya sedang mengembangkan skrip yang memindahkan file di banyak mesin dalam jaringan dan melakukan beberapa tindakan pada host jarak jauh. Saya ingin melihat alur skrip sebelum benar-benar melakukan perubahan pada sistem file. Akan sama membosankan untuk memeriksa semua mesin jarak jauh untuk memperbaiki kesalahan file ...
ysap
1
Tambahan: Untuk melangkah melalui skrip, Anda dapat memulai skrip dengan trap read debugyang akan melakukan pembacaan setelah setiap baris dieksekusi, dan Anda kemudian dapat melangkah secara perlahan dengan enter (ini berguna jika Anda memiliki skrip yang sangat panjang dan ingin menguji untuk pertama kali).
netigger
8

Saya pikir Anda harus mengulangi - namun jika Anda memasukkan perintah ke dalam variabel, Anda dapat menghidupkan dan mematikannya. Juga, perintah itu bisa berfungsi dan secanggih yang Anda inginkan.

#!/bin/bash
echo 'Debug'
  D=echo
  :>| testy
  ls -l testy
  $D rm -f testy
  ls -l testy
echo $'\n\nLive'
  D=
  :>| testy
  ls -l testy
  $D rm -f testy
  ls -l testy

!$ > ./conditional.sh
Debug
-rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy
rm -f testy
-rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy

Live -rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy ls: cannot access testy: No such file or directory

pengguna191016
sumber
Saya meminta tanda kutip di perintah echo / don't-echo, dan kemudian harus digunakan D=evaldi bagian live. Tapi jawaban yang bagus!
Jasper
5

Anda melacak aliran menggunakan opsi -x untuk bash, tetapi ini masih akan menjalankan perintah.

Yang terbaik yang bisa Anda lakukan adalah hanya menempatkan gema atau komentar perintah yang memiliki efek eksternal seperti rm. Setidaknya Anda tidak perlu mengubah setiap baris.

parkydr
sumber
Terima kasih. Saya menyebutkan opsi itu dalam pertanyaan saya, tetapi itu tidak benar-benar menyelesaikan masalah saya.
ysap
Maaf, saya pikir Anda bermaksud menggema setiap baris, -x akan mengurangi ini menjadi beberapa perintah dan menunjukkan kepada Anda evaluasi.
parkydr
4

Saya tidak tahu metode khusus untuk dry run, tetapi kita bisa menggunakan beberapa tindakan pencegahan untuk memahami skrip yang tidak dikenal.

  1. Gunakan lingkungan chroot untuk menjalankan skrip debug Anda. Ini akan bertindak sebagai kotak pasir dan akan memberikan perlindungan terhadap penghapusan / modifikasi file sistem utama.
  2. Gunakan bash -n <script>untuk pemeriksaan sintaks . Dari gnu bash manual https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html

-n Read commands but do not execute them; this may be used to check a script for syntax errors. This option is ignored by interactive shells.

  1. Baca skrip setidaknya sekali. Anda dapat menggunakan pernyataan gema untuk debug seperti disebutkan dalam jawaban oleh user191016 .
    • Carilah kode yang mencurigakan atau rawan bahaya.
    • misalnya terkait dengan rm, perintah yang mempengaruhi / dev / sda dll.
  2. Selalu mencoba menjalankan skrip sebagai pengguna normal, hindari menjalankan skrip yang tidak dikenal sebagai root.
  3. Anda dapat mendefinisikan alias untuk membuat perintah yang dapat memodifikasi file sebagai interaktif di awal skrip Anda. Contoh alias rm="rm -i" alias cp="cp -i" alias mv="mv -i" Untuk stream editor seperti sed sed -i(-i memodifikasi file di tempat tanpa -i itu menjalankan kering untuk sed, periksa halaman manual untuk rincian) Anda dapat menyalin perintah lengkap dan menjalankan. Tepat sebelum perintah aktual itu akan menampilkan output di layar kemudian gunakan perintah untuk menunggu input pengguna untuk melanjutkan. Contoh sed -i <pattern> Ganti dengan sed <pattern> read -p "Press any key..." sed -i <pattern>

Juga selalu disarankan untuk menyimpan titik cadangan di sistem Anda agar data darurat dapat dipulihkan.

Rohit Raj Mishra
sumber
3

Lakukan set –n, atau tambahkan perintah nAnda yang ada set –v. Tetapi karena ini menyebabkan shell tidak mengevaluasi perintah apa pun, bahkan tidak ifatau while, Anda mungkin tidak mendapatkan pandangan yang terlalu baik dari aliran operasional.

Scott
sumber
Terima kasih. Ini adalah awal yang baik, tetapi seperti yang Anda sebutkan, itu tidak membuat saya melihat aliran yang sebenarnya - di mana dalam skrip asli saya, saya memiliki loop atas daftar host jarak jauh.
ysap
3

Berikut ini sedikit konstruksi yang ingin saya gunakan:

#!/bin/sh

verbose=false
really=true

# parse arguments
while [ $# -ge 1 ]
do
  case "$1" in
    -v) verbose=true ;;
    -n) really=false; verbose=true ;;
  esac
  shift
done

doCmd() {
  if $verbose; then echo "$@"; fi
  if $really; then "$@"; fi
}

doCmd make foo
doCmd rm -rf /tmp/installdir
doCmd mkdir /tmp/installdir
doCmd whatever
doCmd blah blah
Edward Falk
sumber
2

Jika Anda ingin agar modifikasi tidak terjadi, Anda dapat menjalankan skrip sebagai pengguna tanpa hak istimewa:

sudo -u nobody ./scr.sh

Dalam contoh Anda, ini akan dijalankan FN="filename"seperti biasa. Meskipun secara teknis mengeksekusi perintah rm -f ${FN}juga, tidak ada yang akan terjadi jika tidak ada yang tidak memiliki izin yang diperlukan untuk menghapus file.

Tentu saja, ini akan menyebabkan masalah dengan alur kerja bersyarat. Fakta bahwa rmperintah gagal dapat mempengaruhi bagian skrip selanjutnya.

Dennis
sumber
Hal-hal yang kita tidak akan pernah mengerti: Mengapa root diperlukan untuk berjalan sebagai tidak ada ...
mjohnsonengr
Pengguna "tidak ada" tidak khusus untuk OS, tetapi Anda dapat menambahkan entri dalam file sudoers yang memungkinkan sudo tanpa kata sandi untuk "tidak ada".
Dennis
Saya tidak tahu. Tampaknya skrip akan berhenti karena beberapa kesalahan atau yang lain sebelum selesai.
Edward Falk