bash 相对路径、lib相对路径

该文主要记录运行一程序导致的问题及解决方法。

情景是这样的:

1. 自己写的一个程序需要开机自启, 当前的root 目录是RO的, 在init.d的启动脚本留有

    S99_lunch_init ,其通过source 指向一可r/w的shell 脚本—— /oem/Lunch.sh, 这就可添加自己的可自启程序带来的可能性。

...

case "$1" in
  start)
        source /oem/Lunch.sh
        ;;
  stop)
        printf "stop finished\n"
        ;;
  *)
        echo "Usage: $0 {start|stop}"
        exit 1
        ;;
esac
exit 0

在这边,有先需要注意source(也可写成 . xxx ,注意.和xxx中间有个空格)和./xxx之间的区别,其中最主要的差别是前者是当前的shell 环境中执行,而后者会launching 一个新的shell 来执行script。

From Bash man page:

. filename [arguments]
source filename [arguments]
       Read  and  execute  commands  from filename in the current shell
       environment and return the exit status of the last command  exe‐
       cuted from filename.  If filename does not contain a slash, file
       names in PATH are used to find the  directory  containing  file‐
       name.   The  file  searched  for in PATH need not be executable.
       When bash is  not  in  posix  mode,  the  current  directory  is
       searched  if no file is found in PATH.  If the sourcepath option
       to the shopt builtin command is turned  off,  the  PATH  is  not
       searched.   If any arguments are supplied, they become the posi‐
       tional parameters when  filename  is  executed.   Otherwise  the
       positional  parameters  are unchanged.  The return status is the
       status of the last command exited within the  script  (0  if  no
       commands  are  executed),  and false if filename is not found or
       cannot be read.

这里强调这两者的区别是应为在shell script 中, 我们一般会通过如下的code 来切换到相对目录。

#!/bin/bash

cd `dirname $0`
pwd

但大家可以自己try 一下, 在source 命令下, pwd 输出的结果是当前的工作目录,也不是shell script 实际的目录。

讲到这,引出了当前的问题。

既然通过source shell_script ,不会切换工作路径, 那如何控制shell script call 的APP 使用的文件相对路径。

2. 当前我的/oem/Lunch 是这样的:

/oem/foo /oem/foo/config.txt

在foo 中,会使用相对路径去访问一些文件, 就会出现find 不到文件的问题,应该当前的工作环境还在/etc/init.d 目录下

    FILE * cfg_fp = fopen( "./res/resxxx.bin", "r"); 

3. 那如何解决呢?

   我这边使用的方法是在APP code 实现切换工作路径,代码就不解释了。主要是利于shell 调用 APP 是带进的argv[0] (/oem/foo)来获得APP 所在的位置(/oem),然后就可以切换到我们想要的相对路径了。

    // cause using relative path in APP,
    // so chage current path to app path
    char * path = strdup(argv[0]);
    if (path == NULL){
        return -1 ; 
    }
    char * dir = dirname(path);
    assert (!chdir(dir));
    printf("%s\n",dir );
    os_free (path);

4. 该文本该结束, 但一个与lib 找寻的问题也与该相对路径的问题相似,一并记录在这里。

LDFLAGS += -L lib/foodir -lfoo -Wl,-rpath,'$$ORIGIN/lib/foodir'

其中-l 和-rpath 的差别有机会我会用一份文档来记录, 这边主要关住-rpath 中的$ORIGIN 变量, 该变量是用来在可执行elf 运行前去哪边寻找.so 的, 如何没有该变量,则在当前的工作目录寻找, 结合前面的情景,即/etc/init.d ,而不是/oem/foo 路径下。

这边需要注意的是'$$ORIGIN',当前我的编译环境下,需要写成这样才能正常的带上该参数。可运行readelf -d xxx.elf 来确认。

 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN/lib/foodir]

 

 

参考link :

  • https://superuser.com/questions/46139/what-does-source-do   bash 中source 与. /xxx的不同
  • https://blog.theerrorlog.com/the-gnu-linker-and-rpath.html  rpath介绍,推荐

你可能感兴趣的:(linux,C)