Jika saya periksa, /proc/1/environ
saya dapat melihat serangkaian 1
variabel lingkungan proses null-byte-delimited . Saya ingin membawa variabel-variabel ini ke lingkungan saya saat ini. Apakah ada cara mudah untuk melakukan ini?
The proc
halaman manual memberi saya potongan yang membantu akan mencetak masing-masing variabel lingkungan secara baris demi baris (cat /proc/1/environ; echo) | tr '\000' '\n'
. Ini membantu saya memverifikasi konten yang benar, tetapi yang benar-benar perlu saya lakukan adalah sumber variabel-variabel ini ke sesi bash saya saat ini.
Bagaimana aku melakukan itu?
sumber
. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/nnn/environ)
, yang akan menangani variabel dengan tanda kutip di dalamnya dengan benar juga."$@"
alih-alih'{}'
. Bagi mereka yang bertanya-tanya tentang--
argumen dalam jawaban yang ditingkatkan: argumen posisibash -c command_string
ditugaskan mulai dari$0
, sementara"$@"
memperluas untuk memasukkan argumen mulai dari$1
. Argumen--
ditugaskan$0
.Di
bash
Anda dapat melakukan hal berikut. Ini akan berfungsi untuk semua konten yang mungkin dari variabel dan menghindarieval
:Ini akan mendeklarasikan variabel baca sebagai variabel shell di shell yang sedang berjalan. Untuk mengekspor variabel ke lingkungan shell yang sedang berjalan:
sumber
Dalam jawaban ini, saya menganggap sistem tempat
/proc/$pid/environ
mengembalikan lingkungan proses dengan PID yang ditentukan, dengan byte nol antara definisi variabel. ( Jadi Linux, Cygwin atau Solaris (?) ).Zsh
(Cukup sederhana seiring berjalannya zsh: pengalihan input tanpa perintah
<FILE
sama dengancat FILE
. Output dari substitusi perintah mengalami ekspansi parameter dengan flag yangps:\000:
berarti “split on null bytes”, dan@
artinya “jika semuanya dalam tanda kutip ganda maka perlakukan setiap elemen array sebagai bidang terpisah ”(generalisasi"$@"
).)Bash, mksh
(Dalam shell ini, pembatas kosong diteruskan ke
read
hasil dalam byte nol menjadi pemisah. Saya menggunakanPWD
sebagai nama variabel sementara untuk menghindari clobber variabel lain yang mungkin akhirnya diimpor. Sementara Anda bisa secara teknis mengimporPWD
juga, itu hanya akan tetap tinggal sampai selanjutnyacd
.)POSIX
Portabilitas POSIX tidak begitu menarik untuk pertanyaan ini, karena hanya berlaku untuk sistem yang memilikinya
/proc/PID/environ
. Jadi pertanyaannya adalah apa yang didukung Solaris - atau apakah Solaris memiliki/proc/PID/environ
, itu tidak digunakan untuk tetapi saya jauh di belakang kurva pada fitur Solaris sehingga mungkin saat ini. Di Linux, utilitas GNU dan BusyBox keduanya null-safe, tetapi dengan peringatan.Jika kita bersikeras pada portabilitas POSIX, tidak ada utilitas teks POSIX yang diperlukan untuk menangani byte nol, jadi ini sulit. Berikut adalah solusi yang mengasumsikan bahwa awk mendukung byte nol sebagai pembatas rekaman (nawk dan gawk lakukan, seperti halnya BusyBox awk, tetapi mawk tidak).
BusyBox awk (yang merupakan versi yang biasa ditemukan pada sistem Linux yang disematkan) tidak mendukung byte nol tetapi tidak diset
RS
ke"\0"
dalamBEGIN
blok dan bukan sintaks baris perintah di atas; Namun itu mendukung-v 'RS="\0"'
. Saya belum menyelidiki mengapa, ini terlihat seperti bug dalam versi saya (Debian wheezy).(Bungkus semua
bariscatatan yang dipisahkan nol dalam tanda kutip tunggal"\047"
, setelah lolos dari tanda kutip tunggal di dalam nilai.)Peringatan
Berhati-hatilah bahwa semua ini dapat mencoba untuk mengatur variabel read-only (jika shell Anda memiliki variabel read-only).
sumber
Saya berputar-putar dengan ini. Saya frustrasi dengan portabilitas byte nol. Itu tidak cocok dengan saya bahwa tidak ada cara yang dapat diandalkan untuk menangani mereka dalam cangkang. Jadi saya terus mencari. Yang benar adalah saya menemukan beberapa cara untuk melakukan ini, hanya beberapa di antaranya yang dicatat dalam jawaban saya yang lain. Tetapi hasilnya setidaknya dua fungsi shell yang bekerja seperti ini:
Pertama saya akan berbicara tentang
\0
pembatas. Ini sebenarnya cukup mudah dilakukan. Inilah fungsinya:Pada dasarnya
od
mengambilstdin
dan menulis kestdout
setiap byte yang diterimanya dalam heksadesimal satu per baris.Saya yakin Anda bisa menebak yang mana
\0null
, kan? Ditulis seperti itu sangat mudah untuk menangani dengan setiapsed
.sed
hanya menyimpan dua karakter terakhir di setiap baris sampai menemukan nol di mana titik itu menggantikan baris baru menengah denganprintf
kode format ramah dan mencetak string. Hasilnya adalah\0null
array yang dibatasi string hex byte. Melihat:Saya mengirim pipa di atas
tee
sehingga Anda bisa melihat output susbstitusi perintah dan hasilprintf
pemrosesan. Saya harap Anda akan melihat bahwa subkulit sebenarnya tidak dikutip juga tetapiprintf
masih dibagi hanya pada\0null
pembatas. Melihat:Tidak ada kutipan pada ekspansi itu - tidak masalah apakah Anda mengutipnya atau tidak. Ini karena nilai gigitan yang
\n
dihasilkan tidak terpisahkan kecuali untuk satu baris yang dihasilkan untuk setiap kalised
mencetak string. Pemisahan kata tidak berlaku. Dan itulah yang memungkinkan ini terjadi:Fungsi di atas digunakan
_zedlmt
untuk${pcat}
aliran kode byte yang disiapkan untuk sumber lingkungan dari setiap proses yang dapat ditemukan di/proc
, atau untuk secara langsung.dot
${psrc}
sama di shell saat ini, atau tanpa parameter, untuk menampilkan output yang diproses sama ke terminal sepertiset
atauprintenv
akan. Yang Anda butuhkan adalah$pid
- file apa pun yang dapat dibaca/proc/$pid/environ
akan dilakukan.Anda menggunakannya seperti ini:
Tetapi apa perbedaan antara ramah manusia dan sumber daya ? Nah, perbedaannya adalah apa yang membuat jawaban ini berbeda dari yang lain di sini - termasuk yang lain. Setiap jawaban lainnya tergantung pada shell mengutip dalam beberapa cara atau yang lain untuk menangani semua kasus tepi. Itu tidak bekerja dengan baik. Tolong percayalah - saya sudah MENCOBA. Melihat:
TIDAK ada jumlah karakter yang funky atau kutipan yang terkandung dapat mematahkan ini karena byte untuk setiap nilai tidak dievaluasi sampai saat konten diambil. Dan kita sudah tahu itu berfungsi sebagai nilai setidaknya sekali - tidak ada penguraian atau perlindungan kutipan yang diperlukan di sini karena ini adalah salinan byte-untuk-byte dari nilai aslinya.
Fungsi pertama mengevaluasi
$var
nama - nama dan menunggu untuk menyelesaikan cek sebelum.dot
sumber di sini-dok di-deskriptor pada file 3. Sebelum sumber itu, itu seperti apa itu. Ini bukti bodoh. Dan POSIX portable. Yah, setidaknya penanganan \ 0null adalah POSIX portable - filesystem / proses jelas spesifik untuk Linux. Dan itu sebabnya ada dua fungsi.sumber
Menggunakan
source
dan memproses substitusi :Segera:
Menggunakan
eval
dan memerintahkan substitusi :The
sed
panggilan dapat diganti denganawk
panggilan:Tapi jangan lupa bahwa itu tidak menghapus variabel lingkungan yang tidak ada dalam pid 1.
sumber
Perlu dicatat bahwa proses dapat memiliki variabel lingkungan yang tidak valid variabel Bash / Sh / * sh - POSIX merekomendasikan tetapi tidak mengharuskan variabel lingkungan memiliki nama yang cocok
^[a-zA-Z0-9_][a-zA-Z0-9_]*$
.Untuk menghasilkan daftar variabel yang kompatibel dengan shell dari lingkungan proses lain, di Bash:
Demikian pula, untuk memuatnya:
Masalah ini muncul hanya sesekali tetapi ketika ...
sumber
Saya pikir ini adalah POSIX portable:
Tapi @Gilles membuat poin yang bagus -
sed
mungkin akan menangani nulls, tapi mungkin tidak. Jadi ada ini (saya benar-benar berpikir begitu kali ini) sebenarnya metode portabel POSIX, juga:Namun, jika Anda memiliki GNU,
sed
Anda hanya perlu:Nah, POSIX portable yang kecuali untuk
/dev/...
yang tidak ditentukan tetapi Anda bisa berharap sintaks itu berlaku sama di sebagian besar Unix.Sekarang jika ini ada hubungannya dengan pertanyaan Anda yang lain , Anda mungkin ingin menggunakannya seperti ini:
Di sini-doc sangat membantu dalam hal itu membuat shell dari bercinta dengan salah satu mengutip kami bekerja keras untuk menangani di subkulit dan juga memberikan kita jalan diandalkan untuk
.dot
sourceable file yang bukan, sekali lagi, subkulit atau shell variabel. Yang lain di sini menggunakan<(process substitution)
bashism yang bekerja dengan cara yang sama - hanya saja itu jelas anonim|pipe
sedangkan POSIX hanya menentukaniohere
untuk di sini-docs dan jadi itu bisa semua jenis file, meskipun, dalam praktiknya, biasanyatemp
file. (dash,
di sisi lain, memang menggunakan anonim|pipes
untuk di sini-docs) . Hal yang disayangkan tentang substitusi proses, apakah itu juga tergantung pada shell - yang mungkin merupakan masalah yang sangat mengganggu jika Anda bekerja dengannyainit
.Ini juga bekerja dengan baik
|pipes
, tetapi kemudian Anda kehilangan lingkungan lagi pada akhirnya ketika|pipe's
negara menguap dengan subkulitnya. Kemudian lagi, ini bekerja:The
sed
Pernyataan itu sendiri bekerja dengan memegang setiap baris dalam memori hingga mencapai yang terakhir, pada saat ia melakukan menggantikan global penanganan mengutip dan memasukkan baris baru di mana yang sesuai dengan penahan pada nulls. Cukup sederhana kok.Pada
dash
gambar Anda akan melihat saya memilih untuk menghindari \ mess dan menambahkan opsiGNU
khusus-r
untuksed
. Tapi itu hanya karena kurang mengetik. Cara kerjanya baik, seperti yang Anda lihat padazsh
gambar.Inilah
zsh
:Dan inilah yang
dash
melakukan hal yang sama:Bahkan lolos terminal terjadi tanpa cedera:
sumber
/proc/PID/environ
. Jadi pertanyaannya adalah apa yang didukung Solaris - atau apakah Solaris memiliki/proc/PID/environ
, tidak digunakan untuk tetapi saya jalan di belakang kurva pada fitur Solaris sehingga mungkin saat ini.)sed
diperlukan untuk menangani heksadesimal ascii, di mana byte nol adalah satu. Selain itu, saya sebenarnya hanya berpikir jika cara ini masih jauh lebih mudah.\xNN
sintaks tidak diperlukan dalam POSIX, bahkan\OOO
sintaks oktal (dalam string C dan awk, ya, tetapi tidak dalam regexps sed)./proc/PID/environ
semuanya (ia memiliki beberapa entri seperti Linux lainnya/proc/PID
, tetapi tidakenviron
). Jadi solusi portabel tidak perlu melampaui alat Linux, artinya GNU sed atau BusyBox sed. Keduanya mendukung\x00
di regexp, sehingga kode Anda se portabel yang diperlukan (tetapi tidak POSIX). Ini terlalu rumit.sumber