在Haskell中设置argv[0]?

9
有没有一种方法可以在Haskell程序中设置argv [0](比如使用ghc编译的程序)?
我发现了System.Environment中的getProgNamewithProgName函数,但似乎它并没有改变ps报告的内容(Ubuntu)。
import System.Environment

main =
  do name <- getProgName
     putStrLn $ "Hello, my name is " ++ name
     withProgName "other" $ do
       newname <- getProgName
       putStrLn $ "Name now set to " ++ newname
       putStrLn "What is your name: "
       -- allow time to run ps
       ans <- getLine
       putStrLn $ "Pleased to meet you, " ++ ans

1
没有可靠和便携的方法来更改 ps 报告的内容,所以如果 GHC 不支持这一点,我不会感到惊讶。 - Fred Foo
2个回答

16

没有一种可移植的方法可以做到这一点,但是在Linux 2.6.9及以上版本中,可以使用prctl()函数以PR_SET_NAME操作更改进程名称,因此我们只需要使用少量的FFI即可从Haskell中使用它。(通常最好检查Hackage上是否有任何绑定,但在这种情况下,我找不到任何绑定)

{-# LANGUAGE ForeignFunctionInterface #-}

import Foreign.C

foreign import ccall "sys/prctl.h prctl"
  prctl :: CInt -> CString -> CULong -> CULong -> CULong -> IO CInt

setProgName :: String -> IO ()
setProgName title =
  withCString title $ \title' -> do
    res <- prctl pr_set_name title' 0 0 0
    return ()
  where pr_set_name = 15

这个方法似乎可以成功地改变ps中显示的程序名称。但是,getProgName返回的值在程序启动时被缓存了,因此您需要与withProgName结合使用才能在程序内部看到更改。


这似乎只会更改“ps -A”、“ps -a”、“ps -d”、“ps -e”等输出中的名称,而“ps a”、“ps -ef”、“ps f”和可能其他一些仍然显示原始命令行参数。 - thomie

3
程序名称在程序启动时就已经固定了,所以任何改变报告的程序名称的机制都是与操作系统相关的。据我所知,标准库中没有这样做的方法,而且快速搜索 Hackage 也没有找到任何相关内容。我不确定是否有任何方法可以在 Linux 中实现这一点,除非使用不同的 argv[0] 重新执行相同的程序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接