首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在码头容器中运行FlexLM许可证服务器

在码头容器中运行FlexLM许可证服务器
EN

Server Fault用户
提问于 2018-07-18 17:41:18
回答 1查看 4.4K关注 0票数 3

我试图在一个码头容器中运行一个FlexLM许可证服务器。我以前做过这件事没有任何问题。但是现在我有了一个供应商(Synopsys)守护进程(snpslmd),它似乎不适合Docker。守护进程抱怨无法打开它的锁文件:/var/tmp/locksnpslmd,但是/var/tmp存在并且是可写的。

下面是来自Docker容器中供应商守护进程的strace:

代码语言:javascript
复制
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 +++**

下面是来自通常在容器外运行的供应商守护进程的相同的strace段:

代码语言:javascript
复制
munmap(0x7f25da4db000, 4096)            = 0
setsid()                                = 15808
openat(AT_FDCWD, "/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
getdents(3, /* 23 entries */, 32768)    = 584
getdents(3, /* 0 entries */, 32768)     = 0
close(3)                                = 0
open("/var/tmp/locksnpslmd", O_RDWR|O_CREAT, 0666) = 3
fcntl(3, F_SETLK, {l_type=F_WRLCK, l_whence=SEEK_CUR, l_start=0, l_len=0}) = 0
stat("/var/tmp/locksnpslmd", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0

有什么想法吗?

EN

回答 1

Server Fault用户

发布于 2020-07-07 14:47:13

之所以会发生这种情况,是因为get申根()返回“”的不同inode编号。还有“.”"/“的子目录。可以使用LD_PRELOAD hack对snpslmd进行修复。

代码语言:javascript
复制
#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);
  }
}

使用

代码语言:javascript
复制
gcc -ldl -shared -fPIC snpslmd-hack.c -o snpslmd-hack.so

使用包装脚本而不是原始snpslmd:

代码语言:javascript
复制
#!/bin/sh
export LD_PRELOAD=snpslmd-hack.so
exec /usr/bin/snpslmd_bin "$@"
票数 4
EN
页面原文内容由Server Fault提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://serverfault.com/questions/922532

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档