Jawaban:
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
.
Ini tidak berfungsi karena fungsi log_f
tidak dideklarasikan di sudo su -
shell yang Anda luncurkan. Sebagai gantinya:
extVAR="yourName"
sudo su - <user> << EOF
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f ${intVAR} ${extVAR}
EOF
Anda harus mendapatkan fungsi yang didefinisikan dalam subkulit root. Itu mungkin bisa, tapi .... Saya tidak tahu apa yang sebagian besar dari barang itu lakukan. Setidaknya - selama tidak sudo
atau su
kebutuhan stdin untuk membaca password - yang harus mendapatkan log_f()
menyatakan.
Saya percaya bahwa Anda bermaksud untuk memperluas nilai-nilai tersebut ke dalam input shell root. Jika Anda tidak bermaksud melakukannya maka Anda harus mengutip EOF
dan vars sendiri.
Dalam kasus saya saya butuhkan untuk melewati array dan memiliki beberapa masalah, tapi telah sukses setelah beberapa saat oleh bergema nilai-nilai array ke env
-key dan membungkus kode dimaksud dalam bash -c '<intended code>'
, dan pada dasarnya memilikinya menciptakan array, misalnya .: INNER_KEY=($<env_key>)
.
Untuk examlpe:
#!/usr/bin/env bash
PLUGINS=(foo bar baz)
sudo -u <some-user> -i env PLUGINS="`echo ${PLUGINS[@]}`" sh <<'EOF'
bash -c '
FOO=($PLUGINS);
echo values: \[${FOO[@]}\];
for pl in ${FOO[@]};
do echo value: $pl;
done;
'
EOF
Masalahnya adalah saya tidak bisa langsung melakukan sesuatu seperti berikut (tidak menggunakan bash -c '...'
):
FOO=($PLUGINS);
for pl in ${FOO[@]};
...