如何判断 Linux 是否运行在虚拟机上

在 WebHostingTalk 论坛上有些国外奸商会把虚拟机当作独立服务器卖,去年7月份的时候就有一位中国同胞上当受骗,并在 WHT 上发帖声讨,证据确凿,甚至连服务商自己也承认,回帖达355篇。这家独立服务器/VPS 提供商 HostATree.com 居然大胆的把 OpenVZ VPS 这种一看就知道是虚拟机的虚拟机当作独立服务器卖,晕,至少也要弄个 VMWare/KVM/Xen HVM 吧(更难发现是虚拟机),用 OpenVZ 这种容器也太欺负人了:)昨天恰好收到网友一封邮件问到了如何判断自己买的是独立服务器还是虚拟机的问题。这里 VPSee 简单介绍一下市面上常用虚拟技术(包括容器技术)的判别小技巧。

判断 OpenVZ/Xen PV/UML

判断 OpenVZ/Xen PV/UML 是最容易的,直接检查 /proc 下的相关目录和文件就可以知道,比如 OpenVZ VPS 上会有 /proc/vz 这个文件;Xen PV 虚拟机上会有 /proc/xen/ 这个目录,并且目录下有一些东西;UML 上打印 /proc/cpuinfo 会找到 UML 标志。写了一个简单的 Python 脚本来检测:

#!/usr/bin/python
# check if a linux system running on a virtual machine (openvz/xen pv/uml)
# written by http://www.vpsee.com

import sys, os

def main():
    if os.getuid() != 0:
        print "must be run as root"
        sys.exit(0)

    # check OpenVZ/Virtuozzo
    if os.path.exists("/proc/vz"):
        if not os.path.exists("/proc/bc"):
            print "openvz container"
        else:
            print "openvz node"

    # check Xen
    if os.path.exists("/proc/xen/capabilities"):
        if (os.path.getsize("/proc/xen/capabilities") > 0):
            print "xen dom0"
        else:
            print "xen domU"

    # check User Mode Linux (UML)
    f = open("/proc/cpuinfo", "r"); t = f.read(); f.close()
    if (t.find("UML") > 0):
        print "uml"

if __name__=="__main__":
    main()

判断 VMware/Xen HVM/KVM

如果使用的是 VMware/Xen HVM/KVM 这样的全虚拟就更难判断一些,最准确的办法是读取 CPUID 来判断,Xen 源代码下面有一段检测是否是 Xen 的 C 语言代码 tools/misc/xen-detect.c,这段代码提供了一个很好的例子,VPSee 重写了代码,用宏替代了函数,增加了对 VMware 和 KVM 的识别,用 gcc 编译后就可以运行:

 
 
 /******************************************************************************
 * xen_detect.c
 *
 * Simple GNU C / POSIX application to detect execution on Xen VMM platform.
 *
 * Copyright (c) 2007, XenSource Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
  
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
  
 static int pv_context;
  
 static void cpuid(uint32_t idx,
 uint32_t *eax,
 uint32_t *ebx,
 uint32_t *ecx,
 uint32_t *edx)
 {
 asm volatile (
 "test %1,%1 ; jz 1f ; ud2a ; .ascii \"xen\" ; 1: cpuid"
 : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
 : "0" (idx), "1" (pv_context) );
 }
  
 static int check_for_xen(void)
 {
 uint32_t eax, ebx, ecx, edx;
 char signature[13];
 uint32_t base;
  
 for ( base = 0x40000000; base < 0x40001000; base += 0x100 )
 {
 cpuid(base, &eax, &ebx, &ecx, &edx);
  
 *(uint32_t *)(signature + 0) = ebx;
 *(uint32_t *)(signature + 4) = ecx;
 *(uint32_t *)(signature + 8) = edx;
 signature[12] = '\0';
  
 if ( !strcmp("XenVMMXenVMM", signature) && (eax >= (base + 2)) )
 goto found;
 }
  
 return 0;
  
 found:
 cpuid(base + 1, &eax, &ebx, &ecx, &edx);
 printf("Running in %s context on Xen v%d.%d.\n",
 pv_context ? "PV" : "HVM", (uint16_t)(eax >> 16), (uint16_t)eax);
 return 1;
 }
  
 int main(void)
 {
 pid_t pid;
 int status;
 uint32_t dummy;
  
 /* Check for execution in HVM context. */
 if ( check_for_xen() )
 return 0;
  
 /* Now we check for execution in PV context. */
 pv_context = 1;
  
 /*
 * Fork a child to test the paravirtualised CPUID instruction.
 * If executed outside Xen PV context, the extended opcode will fault.
 */
 pid = fork();
 switch ( pid )
 {
 case 0:
 /* Child: test paravirtualised CPUID opcode and then exit cleanly. */
 cpuid(0x40000000, &dummy, &dummy, &dummy, &dummy);
 exit(0);
 case -1:
 fprintf(stderr, "Fork failed.\n");
 return 0;
 }
  
 /*
 * Parent waits for child to terminate and checks for clean exit.
 * Only if the exit is clean is it safe for us to try the extended CPUID.
 */
 waitpid(pid, &status, 0);
 if ( WIFEXITED(status) && check_for_xen() )
 return 0;
  
 printf("Not running on Xen.\n");
 return 0;
 }

判断 VirtualBox/Virtual PC

什么?这种家用桌面虚拟机自己装的还会不知道?!如果不知道的话也有办法,在 Linux 下运行 dmidecode 工具然后查找 Manufacturer: innotek GmbH, Manufacturer: Microsoft Corporation 关键字就能对应上 VirtualBox 和 Virtual PC.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值