sudo su -
, yang merupakan cara penulisan yang rumit sudo -i
, membangun lingkungan yang murni. Itulah inti dari shell login. Bahkan dataran sudo
menghapus sebagian besar variabel dari lingkungan. Selanjutnya sudo
adalah perintah eksternal; tidak ada cara untuk meningkatkan hak istimewa dalam skrip shell itu sendiri, hanya untuk menjalankan program eksternal ( sudo
) dengan hak istimewa tambahan, dan itu berarti setiap variabel shell (yaitu variabel yang tidak diekspor) dan fungsi yang didefinisikan dalam shell induk tidak akan tersedia di cangkang anak.
Anda dapat melewati variabel lingkungan dengan tidak menggunakan shell login ( sudo bash
bukan sudo su -
atau sudo -i
) dan mengkonfigurasi sudo untuk membiarkan variabel-variabel ini melalui (dengan Defaults !env_reset
atau Defaults env_keep=…
dalam sudoers
file). Ini tidak akan membantu Anda untuk fungsi (walaupun bash memiliki fasilitas ekspor fungsi, sudo memblokirnya).
Cara normal untuk mendapatkan fungsi Anda di child shell adalah dengan mendefinisikannya di sana. Berhati-hatilah mengutip: jika Anda menggunakan <<EOF
untuk dokumen di sini, konten dokumen di sini pertama kali diperluas oleh shell induk, dan hasil ekspansi itu menjadi skrip yang dilihat oleh shell anak. Yaitu, jika Anda menulis
sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF
ini menampilkan nama pengguna asli, bukan target pengguna. Untuk menghindari fase ekspansi pertama ini, kutip penanda dokumen di sini setelah <<
operator:
sudo -u "$target_user" -i <<'EOF'
echo "$(whoami)"
EOF
Jadi jika Anda tidak perlu meneruskan data dari shell induk ke shell anak, Anda dapat menggunakan dokumen yang dikutip di sini:
#!/bin/bash
sudo -u "$target_user" -i <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}"
EOF
Meskipun Anda dapat menggunakan penanda dokumen yang tidak dikutip di sini untuk meneruskan data dari shell induk ke shell anak, ini hanya berfungsi jika data tidak mengandung karakter khusus apa pun. Itu karena dalam naskah suka
sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF
output whoami
menjadi sedikit kode shell, bukan string. Misalnya, jika whoami
perintah dikembalikan "; rm -rf /; "true
maka shell anak akan menjalankan perintah echo ""; rm -rf /; "true"
.
Jika Anda perlu meneruskan data dari shell induk, cara sederhana adalah mengirimkannya sebagai argumen. Panggil cangkang anak secara eksplisit dan berikan parameter posisi:
#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i sh _ "$extVAR" <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}" "${1}"
EOF
Jika Anda memiliki beberapa variabel untuk dilewati, akan lebih mudah dibaca untuk meneruskannya dengan nama. Panggil env
secara eksplisit untuk mengatur variabel lingkungan untuk shell anak.
#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i env extVAR="$extVAR" sh <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}" "${1}"
EOF
Perhatikan bahwa jika Anda mengharapkan /etc/profile
dan target pengguna ~/.profile
untuk dibaca, Anda harus membacanya secara eksplisit, atau menelepon bash --login
alih-alih sh
.