⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unix faq

📁 UNIX FAQ 中文版
💻
📖 第 1 页 / 共 2 页
字号:
发信人: 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 + -