Chuyển tiếp hàm và biến thành sudo su - <user> << EOF


9

Tôi đã khai báo các hàm và biến trong bash / ksh và tôi cần chuyển tiếp chúng vào sudo su - {user} << EOF:

#!/bin/bash

log_f() {
echo "LOG line: $@"
}

extVAR="yourName"

sudo su - <user> << EOF
  intVAR=$(date)
  log_f ${intVAR} ${extVAR}
EOF

Câu trả lời:


4

sudo su -, đó là một cách viết phức tạp sudo -i, xây dựng một môi trường nguyên sơ. Đó là điểm của một vỏ đăng nhập. Ngay cả một đồng bằng sudoloại bỏ hầu hết các biến từ môi trường. Hơn nữa sudolà một lệnh bên ngoài; không có cách nào để nâng cao các đặc quyền trong chính tập lệnh shell, chỉ chạy một chương trình bên ngoài ( sudo) với các đặc quyền bổ sung và điều đó có nghĩa là bất kỳ biến shell nào (tức là các biến không xuất) và các hàm được xác định trong shell cha sẽ không khả dụng trong Vỏ con.

Bạn có thể chuyển các biến môi trường thông qua bằng cách không gọi shell đăng nhập ( sudo bashthay vì sudo su -hoặc sudo -i) và định cấu hình sudo để cho các biến này đi qua (có Defaults !env_resethoặc Defaults env_keep=…trong sudoerstệp). Điều này sẽ không giúp bạn cho các chức năng (mặc dù bash có một cơ sở xuất khẩu chức năng, sudo chặn nó).

Cách thông thường để có được các chức năng của bạn trong shell con sẽ là xác định chúng ở đó. Hãy cẩn thận khi trích dẫn: nếu bạn sử dụng <<EOFcho tài liệu ở đây, nội dung của tài liệu ở đây trước tiên được mở rộng bởi trình bao cha mẹ và kết quả của việc mở rộng đó trở thành tập lệnh mà trình bao con nhìn thấy. Đó là, nếu bạn viết

sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF

Điều này sẽ hiển thị tên của người dùng ban đầu, không phải người dùng đích. Để tránh giai đoạn mở rộng đầu tiên này, hãy trích dẫn tài liệu đánh dấu ở đây sau <<toán tử:

sudo -u "$target_user" -i <<'EOF'
echo "$(whoami)"
EOF

Vì vậy, nếu bạn không cần truyền dữ liệu từ shell cha sang shell con, bạn có thể sử dụng tài liệu được trích dẫn ở đây:

#!/bin/bash
sudo -u "$target_user" -i  <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}"
EOF

Mặc dù bạn có thể sử dụng một điểm đánh dấu tài liệu không được trích dẫn ở đây để truyền dữ liệu từ vỏ cha sang vỏ con, nhưng điều này chỉ hoạt động nếu dữ liệu không chứa bất kỳ ký tự đặc biệt nào. Đó là bởi vì trong một kịch bản như

sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF

đầu ra whoamitrở thành một bit của mã shell, không phải là một chuỗi. Ví dụ, nếu whoamilệnh trả về "; rm -rf /; "truethì shell con sẽ thực thi lệnh echo ""; rm -rf /; "true".

Nếu bạn cần truyền dữ liệu từ shell cha, một cách đơn giản là truyền nó dưới dạng đối số. Gọi shell con một cách rõ ràng và truyền cho nó các tham số vị trí:

#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i sh  _ "$extVAR" <<'EOF'
  log_f() {
  echo "LOG line: $@"
  }
  intVAR=$(date)
  log_f "${intVAR}" "${1}"
EOF

Nếu bạn có nhiều biến để vượt qua, việc chuyển chúng theo tên sẽ dễ đọc hơn. Gọi envrõ ràng để đặt các biến môi trường cho shell con.

#!/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

Lưu ý rằng nếu bạn mong muốn /etc/profilevà người dùng mục tiêu ~/.profilesẽ được đọc, bạn sẽ phải đọc chúng một cách rõ ràng hoặc gọi bash --loginthay vì sh.


1

Điều này không hoạt động vì chức năng log_fkhông được khai báo trong trình sudo su -bao bạn khởi chạy. Thay thế:

extVAR="yourName"

sudo su - <user> << EOF

log_f() {
echo "LOG line: $@"
}

  intVAR=$(date)
  log_f ${intVAR} ${extVAR}
EOF

Bạn cần lấy hàm được định nghĩa trong lớp con gốc. Điều đó có thể làm điều đó, nhưng .... tôi không biết hầu hết những thứ đó làm gì. Ít nhất - miễn là không phải sudovà cũng không suyêu cầu stdin để đọc một mật khẩu - đó nên được log_f()công bố.

Tôi tin rằng bạn có nghĩa là mở rộng các giá trị đó vào đầu vào của vỏ gốc. Nếu bạn không có ý định làm như vậy thì bạn nên trích dẫn EOFvà chính họ.


1

Trong trường hợp của tôi, tôi cần truyền một mảng vào và gặp một số rắc rối, nhưng sau một thời gian đã thành công bằng cách lặp lại các giá trị của mảng thành một env-key và gói mã dự định vào bash -c '<intended code>', và về cơ bản nó sẽ tái tạo mảng, ví dụ : INNER_KEY=($<env_key>).

Đối với đề thi:

#!/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

Vấn đề là tôi không thể trực tiếp làm điều gì đó như sau (không sử dụng bash -c '...'):

FOO=($PLUGINS);
for pl in ${FOO[@]};
...
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.