Tại sao OS X `install` lỗi trên đầu vào được chuyển hướng khi cùng một phiên bản` install` trên linux hoạt động tốt?


7

Tôi muốn sử dụng installlệnh để tạo một tệp thực thi mới với nội dung được điền trước (ví dụ: với một pwdlệnh duy nhất trong đó).

Vì vậy, tôi đã mở rộng ví dụ này để tạo một tệp thực thi trống mới:

install -b -m 755 /dev/null newfile

vào cái này

install -m755 <(echo pwd) newfile

hoặc là:

echo pwd | install -m755 /dev/stdin newfile

Nơi tôi mong đợi để tạo một newfiletệp thực thi mới sẽ được tạo với nội dung pwdbên trong.

Nó hoạt động trên Linux, tuy nhiên trên OS X thì không thành công với lỗi sau:

  • BSD install( /usr/bin/install)

    cài đặt :: /dev/fd/63Loại tệp không phù hợp hoặc định dạng

  • GNU install( /usr/local/opt/coreutils/libexec/gnubin/install)

    cài đặt: bỏ qua tập tin /dev/fd/63, vì nó đã được thay thế trong khi được sao chép

Tại sao điều này không hoạt động trên Unix, nhưng nó hoạt động trên Linux? Tôi đang thiếu thứ gì? Có cách nào để bỏ qua cảnh báo trên bằng cách sử dụng cú pháp khác nhau ( không tạo tệp trong các lệnh riêng biệt và sử dụng chmodsau đó) không?


Trên cả hai môi trường (Linux & OS X) Tôi có cùng một phiên bản install:

$ install --version
install (GNU coreutils) 8.23

1
Tôi vừa thử cú pháp install -m755 <(echo pwd) newfiletrên một centOS 7máy, và nó hoạt động chính xác. sử dụng cú pháp install -m755 <(echo pwd)> newfiletạo ra lỗi bạn đang nhận mặc dù. Tôi nhận ra điều này không hoàn toàn giúp bạn, nhưng nó cho thấy tiền đề của bạn là ít nhất. Nó sẽ hoạt động
Gravy

2
Nếu bạn sử dụng zsh, bạn có thể thử =(cmd)cú pháp thay vì <(cmd). Từ người đàn ông: "Nếu =(...)được sử dụng thay vì <(...), thì tệp được truyền dưới dạng đối số sẽ là tên của tệp tạm thời chứa đầu ra của quy trình danh sách. Điều này có thể được sử dụng thay cho <biểu mẫu cho một chương trình dự kiến lseek(xem lseek(2)) trên tệp đầu vào. " Nếu không mkfifolà đặt cược tốt nhất của bạn.
Michaël

1
@kenorb Tôi không biết liệu bạn có gặp phải vấn đề này trong nghiên cứu của riêng bạn về vấn đề này không, nhưng thông báo lỗi của bạn dường như đã lan rộng trong số những người dùng Cygwin, thường xuyên sử dụng cp. Đây chỉ là một ví dụ: permalink.gmane.org/gmane.os.cygwin/129935
toxefa

2
@ py4on Làm thế nào điều này có liên quan đến kernel OS X? Điều này xảy ra trên Mac cho cả hai installphiên bản.
kenorb

2
Trừ khi họ chia sẻ cùng một lỗi với một số mã tương tự.
kenorb

Câu trả lời:


1

Bản cài đặt BSD được tìm thấy trên các hệ thống OpenBSD có đoạn mã này trong đó (từ src/usr.bin/xinstall/xinstall.c):

if (!S_ISREG(to_sb.st_mode))
    errc(1, EFTYPE, "%s", to_name);

Điều này phát ra lỗi

install: /dev/fd/4: Inappropriate file type or format

khi phát hiện ra đó /dev/df/4không phải là một tập tin thông thường. (Có một kiểm tra riêng trước đó cho /dev/null)

Đó là khá thẳng về phía trước.

GNU installcó mã này ( src/install.cin coreutils):

  /* Allow installing from non-regular files like /dev/null.
     Charles Karney reported that some Sun version of install allows that
     and that sendmail's installation process relies on the behavior.
     However, since !x->recursive, the call to "copy" will fail if FROM
     is a directory.  */

  return copy (from, to, false, x, &copy_into_self, NULL);

Mã phát ra lỗi đến từ src/copy.c:

  source_desc = open (src_name,
                      (O_RDONLY | O_BINARY
                       | (x->dereference == DEREF_NEVER ? O_NOFOLLOW : 0)));

(một vài dòng bị bỏ qua)

  if (fstat (source_desc, &src_open_sb) != 0)
    {
      error (0, errno, _("cannot fstat %s"), quoteaf (src_name));
      return_val = false;
      goto close_src_desc;
    }

  /* Compare the source dev/ino from the open file to the incoming,
     saved ones obtained via a previous call to stat.  */
  if (! SAME_INODE (*src_sb, src_open_sb))
    {
      error (0, 0,
             _("skipping file %s, as it was replaced while being copied"),
             quoteaf (src_name));

Đây là trong copy_reg()đó sao chép một tập tin thông thường. Các SAME_INODEđánh giá lại macro để sai vì các inodes khác nhau trong hai statcấu trúc *src_sbsrc_open_sb. Việc *src_sbxuất phát từ một stat()hoặc lstat()gọi tên tệp nguồn và src_open_sbtừ fstat()như đã thấy ở trên, trên một mô tả mới mở.

Tôi có thể thấy tại sao việc mở một bộ mô tả tệp mới và so sánh inode của nó với bộ mô tả tệp được cung cấp bởi trình bao ( /dev/fd/4trong trường hợp của tôi) sẽ thất bại, nhưng tôi không thể đặt nó vào những từ xác định.

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.