如何在docker内部运行Flexlm工具启动license

License管理 0 2513 团子精英 收藏

在docker中使用flexlm管理license,大多数daemon都可以正常使用,但是针对新版本的synopsys的daemon确会出现报错,报错如下:

The daemon complains about not being able to open its lock file: /var/tmp/locksnpslmd, but /var/tmp
exists and is writable.

通过跟踪发现:

munmap(0x7fa322830000, 167936)          = 0
setsid()                                = 64
openat(AT_FDCWD, "/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
getdents(3, /* 22 entries */, 32768)    = 568
getdents(3, /* 0 entries */, 32768)     = 0
close(3)                                = 0
write(1, "17:35:24 (snpslmd) Cannot open d"..., 4817:35:24 (snpslmd) Cannot open daemon lock file
) = 48
write(1, "17:35:24 (snpslmd) EXITING DUE T"..., 5817:35:24 (snpslmd) EXITING DUE TO SIGNAL 41 Exit reason 9
) = 58
exit_group(41)                          = ?
+++ exited with 41 +++**

解释原因如下:


发生这种情况是因为getdents()函数中“/”的“.”和“..”子目录返回不同的索引节点编号。可以使用snpslmd的LD_PRELOAD hack修复,保存一下内容为snpslmd-ld.c


#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <dlfcn.h>
#include <string.h>
static int is_root = 0;
static int d_ino = -1;
static DIR *(*orig_opendir)(const char *name);
static int (*orig_closedir)(DIR *dirp);
static struct dirent *(*orig_readdir)(DIR *dirp);
DIR *opendir(const char *name) {
  if (strcmp(name, "/") == 0) {
    is_root = 1;
  }
  return orig_opendir(name);
}
int closedir(DIR *dirp) {
  is_root = 0;
  return orig_closedir(dirp);
}
struct dirent *readdir(DIR *dirp) {
  struct dirent *r = orig_readdir(dirp);
  if (is_root && r) {
    if (strcmp(r->d_name, ".") == 0) {
      r->d_ino = d_ino;
    } else if (strcmp(r->d_name, "..") == 0) {
      r->d_ino = d_ino;
    }
  }
  return r;
}
static __attribute__((constructor)) void init_methods() {
  orig_opendir = dlsym(RTLD_NEXT, "opendir");
  orig_closedir = dlsym(RTLD_NEXT, "closedir");
  orig_readdir = dlsym(RTLD_NEXT, "readdir");
  DIR *d = orig_opendir("/");
  struct dirent *e = orig_readdir(d);
  while (e) {
    if (strcmp(e->d_name, ".") == 0) {
      d_ino = e->d_ino;
      break;
    }
    e = orig_readdir(d);
  }
  orig_closedir(d);
  if (d_ino == -1) {
    puts("Failed to determine root directory inode number");
    exit(EXIT_FAILURE);
  }
}


编译成so文件

gcc -ldl -shared -fPIC snpslmd-ld.c -o snpslmd-ld.so

使用如下方法:

#!/bin/sh
export LD_PRELOAD=snpslmd-hack.so
exec /usr/bin/snpslmd_bin "$@"

也可以在docker启动前加载:

docker run -it --privileged -d -e LD_PRELOAD="/root/snpdlmd-ld.so"  xxxxx xxxx xxxx xxxx



相关推荐:

网友留言:

您需要 登录账户 后才能发表评论

我要评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。
验证码