?? unix faq
字號:
發信人: wshu (樹上的老虎), 信區: Unix
標 題: UNIX FAQ 中文版(三)
發信站: BBS 水木清華站 (Mon May 19 10:07:34 1997)
本篇文章回答以下問題;
3.1)? 要如何得知一個檔案建立的時間?
3.2) 在執行 rsh 的時候要怎樣才能不必等遠方指令執行結束就回到 shell?
3.3) 要怎樣才能截斷一個檔案?
3.4) 為什么執行 find 時所使用的 {} 符號無法達到我預期的結果?
3.5) 我要如何改變一個 symbolic link 的 permission 呢?
3.6) 我要如何 "undelete" 一個檔案?
3.7) 一個process 要怎樣偵測出自己是否在背景狀態執行?
3.8) 為什么在 Bourne shell 當中,對回圈的輸出入轉向無法達到預期的效果?
3.9) 我要怎么在一個 shell script 中或在背景執行 'ftp'、'telnet'、'tip'
等
interactive 的程式呢?
3.10) 在 shell script 或 C 程式當中,要怎樣才能找到某個程式的 process ID
呢?
3.11) 我要怎樣經由 rsh 執行遠方指令時,檢查遠方指令的結束狀態?
3.12) 能不能把 shell 變數傳進 awk 程式當中呢?
3.13) 要怎樣才能避免在記憶體中留下zombie processes?
3.14) 當我要從 pipe 讀一行輸入時,要如何才能讓這行資料像是直接從鍵盤輸
入而非從一個大 block buffer 來的?
3.15) 我要如何在檔案名字中加入日期?
3.16) 為什么有一? script 是用 #! ... 做為檔案的開端?
3.1) 我要如何得知一個檔案建立的時間?
很遺憾,因為檔案建立的時間并未儲存在任何地方,所以答案是無法得知。
關于一個檔案你只能查到最后修改的時間("ls -l"),最后讀取的時間
("ls -lu") 與 inode 改變的使間。有一些 man pages 將最后一個時間當
成是建立的時間,這種說法是錯的。因為 mv、ln、chmod、chmod、chown、
chgrp 等動作都會改變這個時間。
若需更詳盡的說明可參考 "stat(2)" 的 man page.
3.2) 在執行 rsh 的時候要怎樣才能不必等遠方指令執行結束就回到 shell?
(關于我們所討論的 rsh,請參閱問題2.7)
以下這些憑直覺想到的答案都達不到這個效果:
rsh machine command &
或
rsh machine 'command &'
例如, 執行 rsh machine 'sleep 60 &' 這個命令時,我們可以觀察到:rsh并
不會立刻結束,而是等到遠方的 sleep 命令完成以后才結束,即使我們在遠
方使用背景方式執行此命令。所以要怎樣才能讓 rsh 在 sleep命令啟動后立
刻結束呢?
答案如下-
如果您在遠端使用csh:
rsh machine -n 'command >&/dev/null </dev/null &'
如果您在遠端使用 sh:
rsh machine -n 'command >/dev/null 2>&1 </dev/null &'
為什么呢?因為 "-n" 會把 rsh 的stdin接到 /dev/null,因此您可以在本地
機器以背景方式執行整個 rsh 命令。不管是使用 -n 選項或者在指令結尾使
用 "/dev/null",其效果都是一樣的。此外,在遠端機器使用的輸出入轉向(寫
在單引號內的部份)會讓 rsh 認定此次連線可逕行結束(因為已無其他輸
入資料)。
附注: 任何檔案都可以用于遠端機器的輸出入轉向,而不僅限于 /dev/null。
在許多狀況下,這個復雜的命令當中有很多部份都是非必要的。
3.3) 要怎樣才能截斷一個檔案?
BSD 的函數ftruncate() 可以設定檔案的長度。但是并不是每一種版本的動作
都一樣。其他 UNIX 的變種似乎也都支援其他版本的截斷功能。
支援 ftruncate函數的系統多半可歸類為以下三種:
BSD 4.2 - Ultrix, SGI, LynxOS
-無法使用截斷功能來增加檔案長度
-執行截斷動作不會移動檔案指標
BSD 4.3 - SunOS, Solaris, OSF/1, HP/UX, Amiga
-可以用截斷功能來增加檔案長度
-執行截斷動作不會移動檔案指標
Cray - UniCOS 7, UniCOS 8
-無法使用截斷功能來增加檔案長度
-執行截斷動作會移動檔案指標
其他系統則可能在以下四個地方與眾不同:
F_CHSIZE - 只在SCO 上
-有些系統定義了F_CHSIZE 但并沒有真的支援此功能
-動作類似BSD 4.3
F_FREESP - 只在 Interative Unix 上
-有些系統(如Interactive Unix)定義了F_FREESP 但并沒有真的支援此
功能
-動作類似BSD 4.3
chsize() - QNX and SCO
-有些系統(如Interactive Unix)有chsize() 函數但并沒有真的支援
此功能
-動作類似BSD 4.3
「空空如也」-目前找不到這種系統
-也許會有系統完全不支援 truncate功能
FAQ 維護者的注解:以下是我在幾年前從網路抓到的程式,原作者已不可考,
不過S.Spencer Sun <spencer@ncd.com> 也貢獻了一份
F_FREESP的功能。
functions for each non-native ftruncate follow
/* ftruncate emulations that work on some System V's.
This file is in the public domain. */
#include
#include
#ifdef F_CHSIZE
int
ftruncate (fd, length)
int fd;
off_t length;
{
return fcntl (fd, F_CHSIZE, length);
}
#else
#ifdef F_FREESP
/* The following function was written by
kucharsk@Solbourne.com (William Kucharski) */
#include
#include
#include
int
ftruncate (fd, length)
int fd;
off_t length;
{
struct flock fl;
struct stat filebuf;
if (fstat (fd, &filebuf) < 0)
return -1;
if (filebuf.st_size < length)
{
/* Extend file length. */
if (lseek (fd, (length - 1), SEEK_SET) < 0)
return -1;
/* Write a "0" byte. */
if (write (fd, "", 1) != 1)
return -1;
}
else
{
/* Truncate length. */
fl.l_whence = 0;
fl.l_len = 0;
fl.l_start = length;
fl.l_type = F_WRLCK; /* Write lock on file space. */
/* This relies on the UNDOCUMENTED F_FREESP argument to
fcntl, which truncates the file so that it ends at the
position indicated by fl.l_start.
Will minor miracles never cease? */
if (fcntl (fd, F_FREESP, &fl) < 0)
return -1;
}
return 0;
}
#else
int
ftruncate (fd, length)
int fd;
off_t length;
{
return chsize (fd, length);
}
#endif
#endif
3.4) 為什么執行 find 時所使用的 {} 符號無法達到我預期的結果?
Find 指令有一個 -exec 的選項會針對每一個找到的檔案執行一個特殊
的指令。Find 會把出現{}的地方置換成目前找到的檔案名稱。因此,
也許有一天您會使用 find 指令對每一個檔案執行某個指令,或者對
一個目錄執行某個指令。
find /path -type d -exec command {}/\* \;
希望 find 能依序執行以下指令:
command directory1/*
command directory2/*
...
不幸的是,find 只會展開自成一體的 {} token;如果 {} 跟其他字元相連
的話(如:{}/*),那么find將不會以您所想的方式展開 {}, 而是轉換為以
下命令
command {}/*
command {}/*
...
也許您可以把它當成 bug, 也可以把它看成是故意設計的特異功能。但我們
可不愿被目前這個特異功能干擾。所以要怎樣避免這個問題呢?其中一種做
法是寫一個小小的 shell script,名稱就叫做 ./doit 好了,其內容如下:
command "$1"/*
那么您就可以把原來的命令行改寫為
find /path -type d -exec ./doit {} \;
如果您想省掉 ./doit 這個 shell script, 可以這么寫:
find /path -type d -exec sh -c 'command $0/*' {} \;
(這種寫法可行的原因是 "sh -c 'command' A B C ..."指令當中,$0會展開為
A, $1會展開為B, 依此類推)
或者您也可以略施小計使用 sed 來造出您想執行的指令行:
find /path -type d -print | sed 's:.*:command &/*:' | sh
如果您想減少 command 的執行次數,您可以先檢查看看系統中有沒有
xargs 這個指令, xargs會從標準輸入一次讀取一行,并且把這些讀入的資料
合并至一個命令行內。您可以寫成以下命令行:
find /path -print | xargs command
這樣會使以下指令執行一次或多次:
command file1 file2 file3 file4 dir1/file1 dir1/file2
很不幸地,這并不是完美無缺或者萬無一失的解法,輸入 xargs 的文字行
必須以換行字元結尾,所以當檔案名稱當中有奇怪的字元(如換行字元)時,
xargs就會因此而混淆。
3.5) 我要如何改變一個 symbolic link 的 permission 呢?
這個問題沒有意義,因為 symbolic link的 permission 根本不代表什么。
那個 link 所指過去的檔案的 permission 才有意義。
3.6) 我要如何 "undelete" 一個檔案?
某年某月的某一天,要刪除 "*.foo" 卻一不小心打成了 "rm * .foo",
結果發現竟把 "*" 都刪除了。真的是欲哭無淚啊!可是你也只好把這當成
是成長的代價了。
當然一個稱職的系統管理員應當會定期做備份。先問一問你的系統管理員看
你不小心刪除的檔案是不是有備份起來。如果沒有的話,嗯,繼續往下看吧!
不管你是不是真的要刪除一個檔案,當你下了 "rm" 以后,檔案就不見了。
在你 "rm" 一個檔案,系統就不再記得你的檔案是用了硬碟中的哪些 block
了。更糟糕的是,當系統要用到更多的硬碟空間時,就優先取用這些剛放出
來的 block。不過天底下沒有不可能的事。理論上說,若你在下了 "rm" 后,
馬上把系統 shutdown,資料是就得回來的。不過,你得找一個對系統非常
熟悉且肯花費數小時至數天的時間來幫你做這件事專家才行。
當你不小心 "rm" 了一個檔案后,第一個反應或許是為什么不用一個 alias
或在 sh 中的 function 將 "rm" 取代掉,當你下 "rm" 只把檔案搬到一個
垃圾桶之類的地方呢?那如果不小心殺錯檔案就可以挽救,只是要定期清一
清垃圾桶就好了。有兩個理由。第一,大多數的人不認為這是一個好的做法。
這么做的話你會太依賴你的 "rm",有一天到了一個正常的系統中把正常的
"rm" 當成你的 "rm" 來用,那可能會死得很慘。第二,你會發現你花費了
許多不必要的時間在處理垃圾桶里的東西。所以對一個初學者而言呢,用
"rm" 的 -i選項應該就夠了。
如果你有大無畏的精神的話,那好吧,就給你個簡單的答案。寫一個名為
"can" 的指令,功用是將檔案移到垃圾桶里。在 csh(1) 中,將以下的東西
放進 ".login" 里:
alias can 'mv \!* ~/.trashcan' # junk file(s) to trashcan
alias mtcan 'rm -f ~/.trashcan/*' # irretrievably empty trash
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -