Saya sedang mengerjakan skrip shell yang membangun perintah kompleks dari variabel, misalnya seperti ini (dengan teknik yang saya pelajari dari Bash FAQ ):
#!/bin/bash
SOME_ARG="abc"
ANOTHER_ARG="def"
some_complex_command \
${SOME_ARG:+--do-something "$SOME_ARG"} \
${ANOTHER_ARG:+--with "$ANOTHER_ARG"}
Script ini secara dinamis menambahkan parameter --do-something "$SOME_ARG"dan --with "$ANOTHER_ARG"untuk some_complex_commandjika variabel ini didefinisikan. Sejauh ini ini berfungsi dengan baik.
Tetapi sekarang saya juga ingin dapat mencetak atau mencatat perintah ketika saya menjalankannya, misalnya ketika skrip saya dijalankan dalam mode debug. Jadi ketika skrip saya berjalan some_complex_command --do-something abc --with def, saya juga ingin memiliki perintah ini di dalam suatu variabel sehingga saya dapat misalnya log ke syslog.
Bash FAQ menunjukkan teknik untuk menggunakan DEBUGjebakan dan $BASH_COMMANDvariabel (misalnya untuk tujuan debugging) untuk tujuan ini. Saya sudah mencobanya dengan kode berikut:
#!/bin/bash
ARG="test string"
trap 'COMMAND="$BASH_COMMAND"; trap - DEBUG' DEBUG
echo "$ARG"
echo "Command was: ${COMMAND}"
Ini berfungsi, tetapi itu tidak memperluas variabel dalam perintah:
host ~ # ./test.sh
test string
Command was: echo "$ARG"
Saya kira saya harus menggunakan eval untuk memperluas echo "$ARG"ke echo test string(setidaknya saya belum menemukan cara tanpa evalbelum). Berikut ini berfungsi:
eval echo "Command was: ${COMMAND}"
Ini menghasilkan output berikut:
host ~ # ./test.sh
test string
Command was: echo "$ARG"
Command was: echo test string
Tapi saya tidak begitu yakin apakah saya bisa menggunakannya evaldengan aman seperti ini. Saya gagal mencoba mengeksploitasi beberapa hal:
#!/bin/bash
ARG="test string; touch /x"
DANGER='$(touch /y; cat /etc/shadow)'
trap 'COMMAND="$BASH_COMMAND"; trap - DEBUG' DEBUG
echo "$ARG" $DANGER
echo "Command was: ${COMMAND}"
eval echo "Command was: ${COMMAND}"
Tampaknya untuk menangani ini dengan baik, tetapi saya ingin tahu apakah ada orang lain melihat masalah yang saya lewatkan.