【概述】
Install和cp類似,都可以將文件/目錄拷貝到指定的地點。但是,install允許你控制目標文件的屬性。install通常用于程序的makefile,使用它來將程序拷貝到目標(安裝)目錄。
【語法】
install [OPTION]... [-T] SOURCE DEST
install [OPTION]... SOURCE... DIRECTORY
install [OPTION]... -t DIRECTORY SOURCE...
install [OPTION]... -d DIRECTORY...
*如果指定了兩個文件名, `install' 將第一個文件拷貝到第二個
* 如果使用了 `--target-directory' (`-t') 選項,或者如果最后一個文件是一個目錄并且沒有使用`--no-target-directory' (`-T')選項, `install'將每一個源文件拷貝到指定的目錄,目標文件名與SOURCE文件名相同。
* 如果使用了 `--directory' (`-d') 選項, `install' 將逐級創建缺失的目標目錄
【常用選項】
-s:對待拷貝的可執行文件進行strip操作,取出文件中的符號表。(一般在做成nand rom時去除符號表,NFS時為了調試方便,一般不會使用此選項)
-d(--directory):創建制定的目錄結構(逐級創建)。如,指定安裝位置為/usr/local/aaa/bbb,/usr/loacal已存在,install會幫助我們創建aaa和bbb目錄,并把程序安裝到指定位置
If we hand write a Makefile
, we should always stick to install instead of using cp for the installation commands. Not only is it more convenient, but it does things right (cp does things wrong).
For example, if we attempt to update /bin/bash
, which is currently running, with “cp ... /bin/bash
”, we get a “text busy” error. If we attempt to update /lib/libc.so.6
with “cp ... /lib/libc.so.6
”, then we either get “text busy” (in ancient versions of Linux) or breaks each and every running program within a fraction of a second (in recent versions of Linux). install
does the thing right in both situations.
The reason why cp
fails is that it simply attempts to open the destination file in write-only mode and write the new contents. This causes problem because Linux (and all contemporary Unices as well as Microsoft Windows) uses memory mapping (mmap) to load executables and dynamic libraries.
The contents of an executable or dynamic library are mmap’d into the linear address space of relevant processes. Therefore, any change in the underlying file affects the mmap’d memory regions and can potentially break programs. (MAP_PRIVATE
guarantees changes by processes to those memory regions are handled by COWwithout affecting the underlying file. On the contrary, POSIX leaves to implementations whether COW should be used if the underlying file is modified. In fact, for purpose of efficiency, in Linux, such modifications are visible to processes even though MAP_PRIVATE
may have be used.)
There is an option MAP_DENWRITE
which disallows any modification to the underlying file, designed to avoid situations described above. Executables and dynamic libraries are all mmap’d with this option. Unfortunately, it turned out MAP_DENYWRITE
became a source of DoS attacks, forcing Linux to ignore this option in recent versions.
Executables are mmap’d by the kernel (in the execve
syscall). For kernel codes, MAP_DENYWRITE
still works, and therefore we get “text busy” errors if we attempt to modify the executable.
On the other hand, dynamic libraries are mmap’d by userspace codes (for example, by loaders like /lib/ld-linux.so
). These codes still pass MAP_DENYWRITE
to the kernel, but newer kernels silently ignores this option. The bad consequence is that you can break the whole system if you think you’re only upgrading the C runtime library.
Then, how does install
solve this problem? Very simple – unlinking the file before writing the new one. Then the old file (no longer present in directory entries but still in disk until the last program referring to it exits) and the new file have different inodes. Programs started before the upgrading (continuing using the old file) and those after the upgrading (using the new version) will both be happy.
記得在大學的時候在編譯LFS 6 的時候, 一直搞不懂 install 的命令 和 cp 以及和 chmod, chgrp 的區別?
工作之后才明白一個Running 的進程不能隨便進行 cp , 經常會提示 "text busy", 運維部的前輩們給的建議是采用mv 來替代 cp , 今天看起來前輩好像不知道install 這個命令啊.
今天就簡單介紹一下 install 命令.
install copy 文件列表且同時能夠設置文件的屬性(包括 owner, group) , 通常用在 Makefiles 中 用來copy 程序到指定的目錄.
常見的用法有以下3中形式:
1: install -d [option] DIRECTORY [DIRECTORY...] 支持多個. 類似 mkdir -p 支持遞歸.
例如: install -d a/b/c e/f 結果和 mkdir -p a/b/c e/f 一樣.
2: install [option] SOURCE DEST
復制 SOURCE 文件(測試不能是目錄) 到DEST file(文件) .
install a/e c 結果類似 cp a/e c # 注意c必須是文件.
有用選項 -D
install -D x a/b/c # 效果類似 mkdir -p a/b && cp x a/b/c
3: install [option] SOURCE [SOURCE...] DIRECTORY
復制 多個SOURCE 文件到目的目錄.
install a/* d 其中 d 是目錄.
有用選項
-b :自動備份.
-m : 設置安裝文件的權限
-p :保留文件的timestamps. 也就是說文件的timestaamps 和 source 文件一樣. 當我們想要利用安裝文件的mtime來跟蹤文件的build時間而不是 安裝時間.
-s : Strip the symbol tables from installed binary executables.
-S : 備份文件的后綴.
install -S .bak new old #old 文件自動被 mv 為 old.bak.
-v: verbose ,打印install 的文件的詳細信息.
`-c'
Ignored; for compatibility with old Unix versions of `install'. #用來兼容舊版的unix.
-C: (大寫)
安裝文件, 但是如果目標文件和源文件一樣( 判斷方法需要看看代碼確認) 就跳過, 這樣的好處是 能夠保持一樣文件的mtime.