简体   繁体   English

检查 python 脚本是否在 aws 实例上运行

[英]Check if python script is running on an aws instance

I'm trying to set up a python logger to send error emails when it logs an error iff the instance has a tag set.我正在尝试设置一个 python 记录器,以便在它记录错误时发送错误电子邮件,如果实例具有标记集。 I then quickly run into the problem of local dev computers that aren't on aws.然后我很快遇到了不在 aws 上的本地开发计算机的问题。 Is there an easy and fast way to check if the script is being run on aws?有没有一种简单快捷的方法来检查脚本是否正在 aws 上运行?

I was loading the instance data with:我正在加载实例数据:

import boto.utils
from boto.ec2.connection import EC2Connection
metadata = boto.utils.get_instance_metadata()
conn = EC2Connection()
instance = conn.get_only_instances(instance_ids=metadata['instance-id'])[0]

I can of course use a timeout on get_instance_metadata, but there is then a tension between now long to make developers wait vs the possibility of not sending an error email in production.我当然可以在 get_instance_metadata 上使用超时,但是现在很长一段时间之间存在紧张关系,使开发人员等待与在生产中不发送错误电子邮件的可能性。

Can anyone think of a nice solution?谁能想到一个很好的解决方案?

Alternatively, you can check if your environment contains any AWS environmental variables :或者,您可以检查您的环境是否包含任何 AWS 环境变量

is_aws = True if os.environ.get("AWS_DEFAULT_REGION") else False

I chose to inspect if my user name is an ec2 instance: (Not a great solution, but it works)我选择检查我的用户名是否是 ec2 实例:(不是一个很好的解决方案,但它有效)

my_user = os.environ.get("USER")
is_aws = True if "ec2" in my_user else False

AWS instances have metadata, so you could make a call to the metadata service and get a response, if the response is valid, you are @ AWS, otherwise you are not. AWS 实例具有元数据,因此您可以调用元数据服务并获得响应,如果响应有效,则您是@AWS,否则您不是。

for example:例如:

import urllib2
meta = 'http://169.254.169.254/latest/meta-data/ami-id'
req = urllib2.Request(meta)
try:
    response = urllib2.urlopen(req).read()
    if 'ami' in response:
        _msg = 'I am in AWS running on {}'.format(response)
    else:
        _msg = 'I am in dev - no AWS AMI'
except Exception as nometa:
    _msg = 'no metadata, not in AWS'

print _msg

This is just a stab - there are likely better checks but this one will get you the feel for it and you can improve upon it as you see fit.这只是一个尝试 - 可能有更好的检查,但这个检查会让你感觉到它,你可以在你认为合适的时候改进它。 IF you are using OpenStack or another cloud service locally you of course will get a metadata response, so you will have to adjust your check accordingly...如果您在本地使用 OpenStack 或其他云服务,您当然会收到元数据响应,因此您必须相应地调整您的支票......

(you could also do this with cloud-init stuff if you are using some kind of launch tool or manager like chef, puppet, homegrown, etc. Drop an /ec2 file in the file system if it's in AWS, or better yet if local drop a /DEV on the box) (如果您使用某种启动工具或管理器,例如 Chef、puppet、homegrown 等,您也可以使用 cloud-init 的东西来执行此操作。如果它在 AWS 中,则在文件系统中删除 /ec2 文件,或者如果是本地文件则更好在盒子上放一个 /DEV)

Similar to @cgseller, assuming python3, one could do something like:与@cgseller 类似,假设使用 python3,可以执行以下操作:

from urllib.request import urlopen

def is_ec2_instance():
    """Check if an instance is running on AWS."""
    result = False
    meta = 'http://169.254.169.254/latest/meta-data/public-ipv4'
    try:
        result = urlopen(meta).status == 200
    except ConnectionError:
        return result
    return result

I don't think this is really a boto issue.我不认为这真的是博托问题。 EC2 (and boto in turn) don't care or know anything about what scripts you're running on your servers. EC2(以及 boto)不关心或不了解您在服务器上运行的脚本。

If your script has a particular signature -- eg listening on a port -- that would be the best way to check, but shy of that, you can just look for its signature in the OS -- its process.如果您的脚本具有特定的签名——例如监听端口——这将是最好的检查方式,但除此之外,您可以在操作系统中查找它的签名——它的进程。

Use the subprocess module and your preferred bash magic to check if it's running :使用 subprocess 模块和您首选的 bash 魔法来检查它是否正在运行

command = ["ssh", "{user}@{server}", "pgrep", "-fl", "{scriptname}"]
try:
    is_running = bool(subprocess.check_output(command))
except subprocess.CalledProcessError:
    log.exception("Checking for script failed")
    is_running = False

A simple solution would be to check the contents of the file /var/lib/cloud/instance/datasource , which on an Ec2 instance contains DataSourceEc2Local: DataSourceEc2Local :一个简单的解决方案是检查文件/var/lib/cloud/instance/datasource的内容,该文件在 Ec2 实例上包含DataSourceEc2Local: DataSourceEc2Local

$ sudo cat /var/lib/cloud/instance/datasource
DataSourceEc2Local: DataSourceEc2Local

so in Python:所以在 Python 中:

datasource_file = "/var/lib/cloud/instance/datasource"
try:
    with open(datasource_file) as f:
        line = f.readlines()
        if "DataSourceEc2Local" in line[0]:
            print("I'm running on EC2!")
except FileNotFoundError:
        print(f"{datasource_file} not found")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM