如何从Golang程序中设置ulimit -n? [英] How to set ulimit -n from a golang program?

查看:393
本文介绍了如何从Golang程序中设置ulimit -n?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目的是在golang程序中设置ulimit -n,这样我就不必全局设置它,而将其限制在程序中.

找到系统调用setrlimit并获取rlimit. ( http://linux.die.net/man/2/setrlimit )

但是当我尝试使用相同的示例程序时,在设置值时出现错误,提示参数无效.

    package main

    import (
         "fmt"
         "syscall"
     )

    func main() {

        var rLimit syscall.Rlimit

        err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit)

        if err != nil {
                fmt.Println("Error Getting Rlimit ", err)
        }
        fmt.Println(rLimit)

        rLimit.Max = 999999
        rLimit.Cur = 999999

        err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit)
        if err != nil {
            fmt.Println("Error Setting Rlimit ", err)
         }
         err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit)

         if err != nil {
            fmt.Println("Error Getting Rlimit ", err)
         }
         fmt.Println("Rlimit Final", rLimit)
         }

获得的输出为:

george@george-Not-Specified ~/work/odesk/progium/trial $ ./getRlimit 
{4294963002032703 0}
Error Setting Rlimit  invalid argument
Rlimit Final {4294963002032703 999999}
george@george-Not-Specified ~/work/odesk/progium/trial $ sudo ./getRlimit 
[sudo] password for george: 
{4294963002032703 0}
Error Setting Rlimit  invalid argument 
Rlimit Final {4294963002032703 999999}
george@george-Not-Specified ~/work/odesk/progium/trial $ uname -a
Linux george-Not-Specified 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:32:08 UTC 2012 i686 i686 i686 GNU/Linux
george@george-Not-Specified ~/work/odesk/progium/trial $ 

所以我能够得到rlimit 设置限制失败,并返回错误. 即使失败,当我再次使用该值时,MAX值也被更改,但CUR值保持不变. 该错误可能是由于我的内核出现问题还是程序错误?在哪里可以找到更多信息以及如何处理此类问题?

更新:

在完成修复程序后即可使用.

george@george-Not-Specified ~/work/odesk/progium/trial $ go build getRlimit.go 
george@george-Not-Specified ~/work/odesk/progium/trial $ ./getRlimit 
{1024 4096}
Error Setting Rlimit  operation not permitted
Rlimit Final {1024 4096}
george@george-Not-Specified ~/work/odesk/progium/trial $ sudo ./getRlimit                                                                                               
[sudo] password for george: 
{1024 4096}
Rlimit Final {999999 999999}
george@george-Not-Specified ~/work/odesk/progium/trial $ uname -a
Linux george-Not-Specified 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:32:08 UTC 2012    i686 i686 i686 GNU/Linux
george@george-Not-Specified ~/work/odesk/progium/trial $ go version
go version devel +7c42cfa28e24 Tue Jul 30 14:22:14 2013 +1000 linux/386

解决方案

它按预期工作.

setrlimit(2).

软限制是内核为 相应的资源.硬限制是软限制的上限 限制:非特权进程只能将其软限制设置为一个值 范围从0到硬限制,并且(不可逆地)降低其 硬限制.特权进程(在Linux下: CAP_SYS_RESOURCE功能)可以对其中一个进行任意更改 极限值.

rlimit.go:

package main

import (
    "fmt"
    "syscall"
)

func main() {
    var rLimit syscall.Rlimit
    err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit)
    if err != nil {
        fmt.Println("Error Getting Rlimit ", err)
    }
    fmt.Println(rLimit)
    rLimit.Max = 999999
    rLimit.Cur = 999999
    err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit)
    if err != nil {
        fmt.Println("Error Setting Rlimit ", err)
    }
    err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit)
    if err != nil {
        fmt.Println("Error Getting Rlimit ", err)
    }
    fmt.Println("Rlimit Final", rLimit)
}

输出:

$ uname -a
Linux peterSO 3.8.0-26-generic #38-Ubuntu SMP Mon Jun 17 21:43:33 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
$ go build rlimit.go
$ ./rlimit
{1024 4096}
Error Setting Rlimit  operation not permitted
Rlimit Final {1024 4096}
$ sudo ./rlimit
[sudo] password for peterSO:
{1024 4096}
Rlimit Final {999999 999999}

更新:

我成功地为linux/amd64运行了rlimit.go,但没有为linux/386运行.对于Linux 32位发行版,在GetrlimitSetrlimit中有一个Go错误.这些错误已修复.

使用Go default分支tip(包括错误修复),运行以下命令,并使用结果更新问题.

$ uname -a
Linux peterSO 3.8.0-26-generic #38-Ubuntu SMP Mon Jun 17 21:46:08 UTC 2013 i686 i686 i686 GNU/Linux
$ go version
go version devel +ba52f6399462 Thu Jul 25 09:56:06 2013 -0400 linux/386
$ ulimit -Sn
1024
$ ulimit -Hn
4096
$ go build rlimit.go
$ ./rlimit
{1024 4096}
Error Setting Rlimit  operation not permitted
Rlimit Final {1024 4096}
$ sudo ./rlimit
[sudo] password for peterSO: 
{1024 4096}
Rlimit Final {999999 999999}
$ 

My purspose was to set ulimit -n from within a golang program so that I do not have to set it globally but restrict it within the program.

Found systemcalls setrlimit and get rlimit for the same. (http://linux.die.net/man/2/setrlimit)

But when I tried a sample program for the same I was getting an error saying invalid argument while setting the value.

    package main

    import (
         "fmt"
         "syscall"
     )

    func main() {

        var rLimit syscall.Rlimit

        err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit)

        if err != nil {
                fmt.Println("Error Getting Rlimit ", err)
        }
        fmt.Println(rLimit)

        rLimit.Max = 999999
        rLimit.Cur = 999999

        err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit)
        if err != nil {
            fmt.Println("Error Setting Rlimit ", err)
         }
         err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit)

         if err != nil {
            fmt.Println("Error Getting Rlimit ", err)
         }
         fmt.Println("Rlimit Final", rLimit)
         }

The output obtained was :

george@george-Not-Specified ~/work/odesk/progium/trial $ ./getRlimit 
{4294963002032703 0}
Error Setting Rlimit  invalid argument
Rlimit Final {4294963002032703 999999}
george@george-Not-Specified ~/work/odesk/progium/trial $ sudo ./getRlimit 
[sudo] password for george: 
{4294963002032703 0}
Error Setting Rlimit  invalid argument 
Rlimit Final {4294963002032703 999999}
george@george-Not-Specified ~/work/odesk/progium/trial $ uname -a
Linux george-Not-Specified 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:32:08 UTC 2012 i686 i686 i686 GNU/Linux
george@george-Not-Specified ~/work/odesk/progium/trial $ 

So I was able to get the rlimit Setting the limit failed and returned an error. Even though it failed the MAX value got changed when I took the value again but CUR value remains the same. Can this error be due to some issue with my kernel or is it a bad program ? Where can I find more information and how to deal with an issue like this ?

Update :

Works after the fix has been made.

george@george-Not-Specified ~/work/odesk/progium/trial $ go build getRlimit.go 
george@george-Not-Specified ~/work/odesk/progium/trial $ ./getRlimit 
{1024 4096}
Error Setting Rlimit  operation not permitted
Rlimit Final {1024 4096}
george@george-Not-Specified ~/work/odesk/progium/trial $ sudo ./getRlimit                                                                                               
[sudo] password for george: 
{1024 4096}
Rlimit Final {999999 999999}
george@george-Not-Specified ~/work/odesk/progium/trial $ uname -a
Linux george-Not-Specified 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:32:08 UTC 2012    i686 i686 i686 GNU/Linux
george@george-Not-Specified ~/work/odesk/progium/trial $ go version
go version devel +7c42cfa28e24 Tue Jul 30 14:22:14 2013 +1000 linux/386

解决方案

It works as expected.

setrlimit(2).

The soft limit is the value that the kernel enforces for the corresponding resource. The hard limit acts as a ceiling for the soft limit: an unprivileged process may only set its soft limit to a value in the range from 0 up to the hard limit, and (irreversibly) lower its hard limit. A privileged process (under Linux: one with the CAP_SYS_RESOURCE capability) may make arbitrary changes to either limit value.

rlimit.go:

package main

import (
    "fmt"
    "syscall"
)

func main() {
    var rLimit syscall.Rlimit
    err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit)
    if err != nil {
        fmt.Println("Error Getting Rlimit ", err)
    }
    fmt.Println(rLimit)
    rLimit.Max = 999999
    rLimit.Cur = 999999
    err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit)
    if err != nil {
        fmt.Println("Error Setting Rlimit ", err)
    }
    err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit)
    if err != nil {
        fmt.Println("Error Getting Rlimit ", err)
    }
    fmt.Println("Rlimit Final", rLimit)
}

Output:

$ uname -a
Linux peterSO 3.8.0-26-generic #38-Ubuntu SMP Mon Jun 17 21:43:33 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
$ go build rlimit.go
$ ./rlimit
{1024 4096}
Error Setting Rlimit  operation not permitted
Rlimit Final {1024 4096}
$ sudo ./rlimit
[sudo] password for peterSO:
{1024 4096}
Rlimit Final {999999 999999}

UPDATE:

I successfully ran rlimit.go for linux/amd64, you failed for linux/386. There were a Go bugs in Getrlimit and Setrlimit for Linux 32-bit distributions. These bugs have been fixed.

Using the Go default branch tip (to include the bug fixes), run the following, and update your question with the results.

$ uname -a
Linux peterSO 3.8.0-26-generic #38-Ubuntu SMP Mon Jun 17 21:46:08 UTC 2013 i686 i686 i686 GNU/Linux
$ go version
go version devel +ba52f6399462 Thu Jul 25 09:56:06 2013 -0400 linux/386
$ ulimit -Sn
1024
$ ulimit -Hn
4096
$ go build rlimit.go
$ ./rlimit
{1024 4096}
Error Setting Rlimit  operation not permitted
Rlimit Final {1024 4096}
$ sudo ./rlimit
[sudo] password for peterSO: 
{1024 4096}
Rlimit Final {999999 999999}
$ 

这篇关于如何从Golang程序中设置ulimit -n?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆