Linux系统中的环境变量 --命令行参数,PATH,通过代码获取环境变量,本地变量

目录

1. 命令行参数

2.环境变量的基本概念

3. 查看环境变量方法

4. 常见的环境变量

4.1 PATH

4.2 HOME

4.3 其他环境变量

5. 环境变量相关的命令 

6. 通过代码如何获取环境变量

7. 环境变量的特性和本地变量


1. 命令行参数

        C语言中main()函数其实是有参数。

#include <stdio.h>

int main(int argc, char *argv[])
{
    return 0;
}

        argv[] 是个字符指针数组,指向一个一个命令行参数字符串,数组中最后一个元素为NULL,表示到达结尾。argc 是上述 argv[] 数组元素的个数。
        用以下代码演示 argc 和 argv[] 的存在和作用。

#include <stdio.h>

int main(int argc, char* argv[])
{
        for (int i = 0; i < argc; i++)
        {
                printf("argv[%d]: %s\n", i, argv[i]);
        }
        return 0;
}

        上述代码依次会打印出命令行中程序执行的命令和选项。这里的命令(./code)和选项(a, b, c)在下面统称为命令行参数。        

        命令行参数的用途是使程序能够通过不同的选项实现不同的子功能。

知识点1

        main函数的命令行参数,是实现程序不同子功能的方法。Linux 系统中的指令也是用C语言写的,所以main函数的命令行参数也是指令选项的实现原理。

        如下代码简单模拟指令的选项功能。

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
        if (argc != 2)
        {
                printf("Usage: %s [-a|-b|-c]\n", argv[0]);
                return 1;
        }

        const char *arg = argv[1];
        if (strcmp(arg, "-a") == 0)
                printf("这是功能1\n");
        else if (strcmp(arg, "-b") == 0)
                printf("这是功能2\n");
        else if (strcmp(arg, "-c") == 0)
                printf("这是功能3\n");
        else
                printf("Usage: %s [-a|-b|-c]\n", argv[0]);

        return 0;
}

知识点2

        进程在运行的时候拥有一张argv表,用来存储所输入的每个命令行参数,实现选项功能。

2.环境变量的基本概念

        环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。

        例如在编写C/C++代码链接动静态库时,我们所链接的动静态库不知道在哪,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。

        环境变量通常具有某些特殊用途,在系统当中通常具有全局特性。

3. 查看环境变量方法

env //罗列出所以的环境变量

        环境变量是以 名称=内容 的形式进行展现的。 

echo $NAME //NAME:环境变量名称

4. 常见的环境变量

4.1 PATH

        PATH:系统中搜索命令的默认搜索路径。

        下面在当前工作目录(/home/csq/linux-learning-notes-and-code1/lesson15)下创建一个hello.c文件,编译为hello二进制文件:

#include <stdio.h>

int main()
{
        printf("hello world\n");
        return 0;
}

        查看当前的PATH环境变量,发现当前工作目录没有在环境变量PATH中,所以只能使用./hello来执行程序。使用 hello 直接程序,bash找不到文件

        使用下列命令在PATH环境变量中添加当前工作目录

export PATH=$PATH:/home/csq/linux-learning-notes-and-code1/lesson15

        这样就能在当前工作目录中直接运行 hello 来执行程序了。 

        如下还有其他的方法不带路径直接就可以运行:

        1. 将自己写的二进制程序拷贝到环境变量PATH中存在的目录下,但是不推荐这样,因为PATH环境变量中默认存在的目录都是与系统配置相关的目录,如果将自己的程序拷贝到这些目录中,可能会污染系统指令的环境等。

        2. 将当前的工作目录信息拷贝到系统相关配置文件中,使系统一启动就将该目录加载到环境变量PATH中。在CentOS7系统中,家目录下有两个隐藏文件 .bashrc 和 .bash_profile,修改.bash_profile中的环境变量PATH路径即可在启动程序时自动加载修改后的环境变量PATH。

知识点1:

        环境变量是内存级的环境变量,每次启动一个bash,在bash进程中向内存申请一段空间来存储环境变量,每次重新启动系统时,之前修改过的环境变量都会重置,默认的环境变量最开始是系统相关配置文件中读取的。

知识点2:
        bash进程启动时,会从系统中读取环境变量,形成一张环境变量表。也是一个字符指针数组,每个元素指向一个key - value 的环境变量长字符串。env查询的时候就是打印这张表中元素指向的内容。

        每个程序都会收到⼀张环境表,环境表是⼀个字符指针数组,每个指针指向⼀个以’\0’结尾的环境字符串

知识点3:

        执行 "ls -a -l "命令时,首先bash先拿到这个字符串,然后通过分割字符串,形成命令行参数表,然后去PATH环境变量的路径中查找 " ls " 命令,如果存在,就拼接命令路径创建子进程执行该命令。

4.2 HOME

        HOME:指定用户的主工作目录(即用户登录到Linux系统中时默认的目录)。

echo $HOME //查看环境变量HOME

         当执行 cd ~ 为什么会直接转到 /home/csq 中,因为在执行这条命令时,把 ~ 替换为环境变量 /HOME 中存储的目录,所以直接就跳转到 /home/csq 中了。

        切换为 root 用户,环境变量HOME则会变为 /root.

4.3 其他环境变量

        SHELL:当前Shell,代表的是使用哪个版本的Shell,它的值通常是/bin/bash这个目录。

        USER:当前用户是谁。

        LOGNAME:当前登录的用户是谁。

        HISTSIZE:当前用户存储历史命令的最大的数量。

        HOSTNAME:表示当前主机的主机名。

        PWD:表示当前的工作目录。

        OLDPWD:表示切换前的工作目录。cd - 命令中的 - 就是 OLDPWD对应的值。

       知识点1:

        su 命令相当于对当前用户提权,并不会更新环境变量中的USER和LOGNAME。su - 命令相当于使用root账号重新登录,会将USER和LOGNAME更新为root。

5. 环境变量相关的命令 

echo $xxx //xxx表示环境变量名,查看指定的环境变量内容
env //查看当前用户的所有环境变量
export xxx=*** //给当前用户增加一个环境变量,环境变量名为xxx,环境变量内容为***

unset xxx //xxx表示环境变量名,表示删除一个环境变量

6. 通过代码如何获取环境变量

        1. 通过命令行参数进行获得。

        第一章讲命令行参数时,其实main函数的参数最多可以有三个,如下:

#include <stdio.h>

int main(int agrc, char *argv[], char *env[])
{
    return 0;
}

        用下列程序遍历父进程(bash)的环境变量表

#include <stdio.h>
#include <string.h>

//main函数有参数吗?有
//最有可以有几个?3个
//该参数是父进程传递给我们的
int main(int argc, char *argv[], char *env[])
{
        (void)argc;
        (void)argv;

        for (int i = 0; env[i]; i++)
        {
                printf("env[%d]-> %s\n", i, env[i]);
        }

        return 0;
}

知识点1:
        main函数只是我们当前编写的代码的入口,不是程序启动的入口,当程序启动的时候会先调用一个start函数,检查main函数中参数的个数,然后把参数传给main函数,然后调用main函数执行我们自己的代码。

        下面是上述代码汇编语言中_start函数中调用main函数: 

 知识点2:
        环境变量会被子进程继承,所以环境变量在系统中具有全局特性。但是如果任意一个子进程想修改环境变量,就和之前进程中的数据一样,会发生写时拷贝。

         2. 通过getenv()函数获取环境变量

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[], char *env[])
{
        (void)argc;
        (void)argv;
        (void)env;

        char *value = getenv("PATH");
        if (value == NULL)
                return 1;
        printf("PATH->%s\n", value);
        return 0;
}

         写一个程序,只能让自己一个人用,连root都不能执行。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[], char *env[])
{
        (void)argc;
        (void)argv;
        (void)env;

        const char *who = getenv("USER");
        if (who == NULL) return 1;

        if (strcmp(who, "csq") == 0)
        {
                printf("这是程序的正常执行逻辑\n");
        }
        else
        {
                printf("Only csq!!!\n");
        }
        return 0;
}

        当使用 csq 用户执行时: 

        当使用 root  用户执行时:

知识点1:

        为什么子进程要继承环境变量?

                因为继承环境变量之后,子进程就可以结合环境变量来定制个性化操作,比如上述的编写一个只能用于一个人用的程序。 

         3. 使用全局变量char **environ来获取环境变量

                该全局变量指针,指向环境变量表的第一个元素(第一个环境变量的地址),所以是一个二级指针。

        用下列程序进行演示:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

extern char **environ;

int main(int argc, char *argv[], char *env[])
{
        (void)argc;
        (void)argv;
        (void)env;

        for (int i = 0; environ[i]; i++)
        {
                printf("env[%d]-> %s\n", i, environ[i]);
        }
        return 0;
}

7. 环境变量的特性和本地变量

       bash会记录两套变量:1.环境变量 2.本地变量:不会被子进程继承,只在bash内部使用。

                环境变量:具有全局特性。

                本地变量:在shell中可以使用 i=10 直接定义本地变量,使用 echo $i 可以进行查询, unset i 取消变量 i 。

export i //i为本地变量名,可以将本地变量i导入到环境变量中

知识点1:
        命令行输入的命令都是bash的子进程,因为进程之间具有独立性,export导入环境变量按道理是不能导入到父进程bash中的,但是为什么可以使用export将环境变量导入到父进程bash中呢?

                因为export是一种内建命令(built-in command),这种命令不需要创建子进程,而是让bash自己亲自执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值