linux不产生临时文件的命令,linux设置临时环境变量命令
暂存文件
通常,程序需要使用文件形式的临时存储。这可能是存储计算的中间结果,也可能是实际操作前做的文件拷贝备份。例如,数据程序在删除记录时会使用临时文件。文件会收集需要保存的数据库实体,然后在操作结束时,临时文件会变成新的数据库,原来的会被删除。
临时文档的大量使用隐藏了他的一个缺点。我们必须小心确保程序会选择一个唯一的名字来使用临时文件。如果不是,因为Linux是一个多任务系统,可能会有另一个同名的程序,这两个程序会互相影响。
tmpnam函数可以生成一个唯一的临时文件名:
#包含stdio.h
char * tmpnam(char * s);
tmpnam函数将返回一个不同于现有文件的可用文件名。如果字符串不为空,文件名也将被写入其中。后续的tmpnam函数调用会覆盖用于返回值的语句存储,所以如果多次调用tmpnam函数,实际上会使用一个字符串参数。假定该字符串的长度至少为L_tmpnam个字符。在一个程序中,tmpnam最多可以被调用TMP_MAX,每次都会生成一个不同的文件名。
如果临时文件被立即使用,那么我们可以使用tmpfile函数来命名它并打开它。这很重要,因为另一个程序将创建一个与tmpnam返回的名称相同的文件。tmpfile函数可以防止这种情况发生:
#包含stdio.h
FILE * tmpfile(void);
tmpfile函数返回一个指向唯一临时文件的流指针。该文件将被打开进行读写,并且在关闭对该文件的所有引用后,该文件将被自动删除。
如果出现错误,tmpfile将返回一个空指针并设置errno变量。
测试-tmpnam和tmpfile
让我们实际看看这两个函数的用法:
#包含stdio.h
int main()
{
char tmpname[L _ tmpnam];
char *文件名;
FILE * tmpfp
filename=tmpnam(tmpname);
printf("临时文件名为:%s/n ",文件名);
tmpfp=tmpfile();
中频(tmpfp)
printf("打开一个临时文件OK/n ");
其他
perror(" tmpfile ");
退出(0);
}
当我们编译正在运行的程序tmpnam.c时,可以看到tmpnam生成的唯一文件名:
$ ./tmpnam
临时文件名是:/tmp/file2S64zc
打开了一个临时文件OK
操作原理
这个程序调用tmpnam来生成一个具有唯一文件名的临时文件。如果我们想使用这个临时文件,我们可以立即打开它,从而降低另一个程序用相同的文件名打开这个文件的风险。tmpfile调用将同时创建并打开一个临时文件,从而避免了这种风险。事实上,在编译使用该函数的程序时,GNU C编译器也会给出使用tmpnam的警告。
旧的Unix系统有另一种方法,通过使用mktemp和mkstemp函数来生成临时文件名。这些都是Linux系统支持的,类似于tmpnam。不同的是,我们可以为临时文件名指定一个模板,这样我们可以更好地控制它的位置和名称:
#包含stdlib.h
char * mktemp(char * template);
int mkstemp(char * template);
mktemp函数从指定的模板生成一个唯一的文件名。模板必须以6 x开头。mktemp函数用唯一可用的文件名字符替换这些x字符。他返回一个指向生成的字符串的指针,如果不能生成唯一的文件名,则返回一个空指针。
mkp函数在创建和打开临时文件方面类似于tmpfile。文件名的生成方式与mktemp相同,但返回的结果是一个开放的底层文件描述符。
一般情况下,我们应该使用创建和打开函数tmpfile和mkstemp,而不是tmpnam和mktemp。
用户信息
除了init,所有的Linux程序都是由其他程序或用户启动的。我们将学习更多关于如何运行程序,或过程,交互等。在第11章。用户通常通过负责命令的外壳来启动程序。我们已经看到,程序可以通过检测其环境变量和读取系统时钟来确定其环境信息。一个程序也可以查看正在使用它的用户的信息。
当用户登录到Linux系统时,他有一个用户名和密码。如果这些被验证,系统将向用户提供一个外壳。通常,用户有一个唯一的用户ID,称为UID。Linux运行的所有程序都是在用户的行为和与之相关的UID上运行的。
我们可以设置一个程序运行,使它看起来像是另一个用户启动的。当程序拥有其UID的权限集时,它的运行看起来就像是可执行文件的所有者启动了它。当执行su命令时,该程序就像由超级用户启动一样运行。然后他会验证用户的访问权限,将其UID改为目标用户的UID,然后执行目标用户的登录shell。这允许程序像由另一个不同的用户启动一样运行,这通常由系统管理员用来执行维护任务。
因为UID是用户识别的关键,我们就从这里开始讨论吧。
UID有自己的类型——UID _ t——在sys/types.h中定义,他通常是一个小整数。有些是由系统预先定义的;其他的由系统管理员在新用户添加到系统中时创建。通常,用户的UID值大于100。
#包含sys/types.h
#包括unistd.h
uid _ t getuid(void);
char * getlog in(void);
getUID函数返回与程序相关的UID值。这通常是启动程序的用户的UID值。
getlogin函数返回与当前用户相关联的登录名。
文件/etc/passwd包含一个处理用户帐户的数据库。每个用户一行,包含用户名、加密密码、用户ID UID、组ID GID、全名、主目录和默认shell。这里有一个例子:
尼尔:zBqxfqedfpk:500:100:尼尔马修:/home/尼尔:/bin/bash
如果我们想写一个程序来确定启动该程序的用户的UID,我们将扩展它来查看密码文件,以找到用户的登录名和全名。我们不建议这样做,因为目前的类Unix系统已经从使用简单的密码文件迁移到了加强系统安全性。包括Linux在内的许多系统都可以选择使用shadwo密码文件,该文件根本不包含任何有用的加密密码信息(通常存储在/etc/shadow中,用户无法读取)。为此,系统定义了一系列功能,为用户信息提供一个标准高效的程序接口:
#包含sys/types.h
#包含pwd.h
struct passwd * getpwuid(uid _ t uid);
struct passwd * getpwnam(const char * name);
密码结构passwd在pwd.h中定义,包含以下成员:
成员描述
Char *pw_name用户登录名
Uid_t pw_uid UID值
Gid _ tpw _ gidgidgid值
Char *pw_dir用户主目录
char *pw_gecos用户的全名
Char *pw_shell用户默认shell
一些Unix系统使用不同的名称来表示用户的完整域名:在一些系统上,比如Linux,它是pw_gecos,在另一个系统上,它是pw_comment。这意味着我们不建议使用该域。
getpwuid和getpwnam函数都返回一个指向对应于用户的密码结构的指针。对于getpwUID函数,用户由UID标识,而对于getpwnam函数,用户由login标识。如果出错,它们都将返回一个空指针并设置errno变量。
测试用户信息
下面是一个程序user.c,它将从密码数据库中获取一些用户信息:
#包含sys/types.h
#包含pwd.h
#包含stdio.h
#包括unistd.h
int main()
{
uid _ t uid
gid _ t gid
结构密码* pw
uid=getuid();
GID=getgid();
printf("用户是%s/n ",getlog in());
printf("用户id:uid=% d,gid=%d/n ",uid,GID);
pw=getpwuid(uid);
printf(" UID passwd entry:/n name=% s,uid=%d,gid=%d,home=%s,shell=%s/n ",
pw- pw_name,pw- pw_uid,pw- pw_gid,pw- pw_dir,pw-pw _ shell);
pw=getpwnam(" root ");
printf("根密码条目:/n ");
printf("名称=%s,uid=%d,gid=%d,主目录=%s,外壳=%s/n ",
pw- pw_name,pw- pw_uid,pw- pw_gid,pw- pw_dir,pw-pw _ shell);
退出(0);
}
程序输出如下,不同系统上的输出结果可能略有不同:
$ ./用户
用户是尼尔
用户id:uid=500,gid=100
UID密码条目:
name=neil,uid=500,gid=100,home=/home/neil,shell=/bin/bash
根密码条目:
name=root,uid=0,gid=0,home=/root,shell=/bin/bash
操作原理
这个程序将调用getUID函数来获取当前用户的UID值。这个UID将在getpwuid函数中用来获取详细的密码文件信息。作为对比,我们演示了如何在getpwnam函数中指定用户名root来获取用户信息。
要遍历密码文件信息,我们可以使用getpwent函数。这将获得连续的文档实体:
#包含pwd.h
#包含sys/types.h
void end pwent(void);
struct passwd * getp went(void);
void setp pent(void);
Getpwent函数将依次返回每个用户的信息。当到达文件末尾时,他将返回一个空指针。一旦搜索完所有有效的实体,我们就可以使用endpwent函数来结束处理。setpwent函数可以将密码文件中的指针重置为指向文件的开头,这样下次调用getpwent函数时就可以重新开始遍历。这些函数的操作类似于第三章讨论的目录遍历函数opendir,readdir,closedir CloseDir。
用户组标识可以通过另一个不常用的功能获得:
#包含sys/types.h
#包括unistd.h
uid _ t geteuid(void);
GID _ t getgid(void);
GID _ t get egid(void);
int setuid(uid _ t uid);
int setgid(GID _ t GID);
我们可以查看系统手册页,获得更多关于组id和有效用户ID的详细信息,虽然我们会发现我们根本不需要操作这些功能。