我正在尝试编写一个shell脚本,在运行时,将设置一些将在调用者的shell中保留的环境变量.
setenv FOO foo
Run Code Online (Sandbox Code Playgroud)
在csh/tcsh中,或
export FOO=foo
Run Code Online (Sandbox Code Playgroud)
在sh/bash中只在脚本执行期间设置它.
我已经知道了
source myscript
Run Code Online (Sandbox Code Playgroud)
将运行脚本的命令而不是启动新的shell,这可能导致设置"调用者"环境.
但这里有一个问题:
我希望这个脚本可以从bash或csh调用.换句话说,我希望任何一个shell的用户都能够运行我的脚本并改变他们的shell环境.所以'source'对我来说不起作用,因为运行csh的用户无法获取bash脚本,而运行bash的用户无法获取csh脚本.
有没有合理的解决方案不需要在脚本上编写和维护两个版本?
std::filesystem
在C++ 17上,std::experimental::filesystem
对于许多前C++ 17编译器来说,基于boost::filesystem
并且几乎所有它都很明显地移植到较新的std.
但我认为不std::filesystem
相同boost::filesystem::unique_path()
.
我没有注意到std中的等价物吗?或者我是否应该采用一种推荐的方法来模仿实现?
boost::filesystem
当我的代码注意到它在支持的平台上进行编译时,我真的希望能够替换依赖std::filesystem
,并且unique_path()
是我转换中唯一不明显的部分.
我知道strtol和strtof比atoi/atof更受欢迎,因为前者检测错误,而且当涉及非base-10时,strtol比atoi更灵活.
但我仍然对某些事情感到好奇:OS X上的'man atoi'(或atof)(虽然不在Linux上!)提到atoi/atof不是线程安全的.坦率地说,我很难想象atoi或atof的可能实现是不是线程安全的.有人知道为什么手册页会这么说吗?这些功能在OS X或任何其他平台上实际上是不安全的吗?如果它们是,那么为什么图书馆不会根据strtol定义atoi,因此是安全的?
从命令行启动的运行C或C++程序的最佳方法是将其置于后台,相当于用户是否从命令末尾的'&'启动了unix shell?(但用户没有.)这是一个GUI应用程序,不需要任何shell I/O,因此没有理由在启动后绑定shell.但是我希望shell命令启动在没有'&'(或Windows)的情况下自动后台运行.
理想情况下,我想要一个适用于Linux,OS X和Windows的解决方案.(或者我可以用#ifdef选择单独的解决方案.)可以假设这应该在执行开始时完成,而不是在中间的某个地方.
一种解决方案是让主程序成为启动真实二进制文件的脚本,小心地将其放入后台.但是需要这些耦合的shell /二进制对似乎并不令人满意.
另一个解决方案是立即启动另一个执行版本(带有'system'或CreateProcess),使用相同的命令行参数,但将子项放在后台然后让父出口.但与将自身置于背景中的过程相比,这似乎很笨拙.
在几个答案之后编辑:是的,fork()(或系统()或Windows上的CreateProcess)是一种解决这个问题的方法,我在原始问题中暗示过.但是所有这些解决方案都使得SECOND流程成为背景,然后终止原始流程.我想知道是否有办法将现有流程放入后台.一个区别是,如果应用程序是从记录其进程ID的脚本启动的(可能是为了以后的查杀或其他目的),新分叉或创建的进程将具有不同的ID,因此任何启动脚本都无法控制,如果你看到我得到了什么.
编辑#2:
fork()不是OS X的好解决方案,其中'fork'的手册页说如果使用某些框架或库则它是不安全的.我试过了,我的应用程序在运行时大声抱怨:"进程已分叉,你不能安全地使用这个CoreFoundation功能.你必须执行()."
我对daemon()感兴趣,但是当我在OS X上尝试它时,它给出了相同的错误消息,所以我认为它只是fork()的一个花哨的包装器并且具有相同的限制.
请原谅OS X中心主义,它恰好是我眼前的系统.但我确实在寻找所有三个平台的解决方案.
如果我正在构建一个库,我假设库中的某些"客户"可能只使用C++ 11,那么我可以使用C++ 14为其内部编译库本身吗?与C++ 11相比,是否存在API/ABI /链接兼容性问题?只要我避免使用公共API中的某些新功能,使用C++ 14实现和构建库是否安全?如果是这样,我必须避免哪些内容?或者在最终软件项目中混合使用C++ 11和C++ 14本质上是不兼容的?
它是一个跨平台的库,BTW,所以我需要在Linux,OSX和Windows上构建它.
使用boost :: filesystem :: exists时,我遇到了一些奇怪的情况.如果您尝试检查未准备好的驱动器上的文件是否存在或者没有介质,则会抛出basic_filesystem_error.至于我对bfs :: exists的大部分用法都很关注,如果驱动器没有准备好,则意味着该文件不存在.
我可以用try-catch包装我的调用以正确处理这个条件,但是它变得有点麻烦并且使代码有点笨拙.更糟糕的是,这意味着我正在使用basic_filesystem_error的特殊情况进行流控制,这意味着如果出现该异常的不同原因,我将不再适当地处理它.
出现这种情况的一般情况是,如果我尝试检查CD或DVD驱动器上是否存在文件.我以前的代码是:
if( bfs::exists( myFilePath ) )
{
...
}
Run Code Online (Sandbox Code Playgroud)
变为:
bool fileExists( false );
try
{
fileExists = bfs::exists( myFilePath );
}
catch( bfs::basic_filesystem_error<bfs::path> e )
{
fileExists = false;
}
if( fileExists )
{
...
}
Run Code Online (Sandbox Code Playgroud)
我并不太喜欢在我现有的代码库中进行这种改变的想法.
我正在考虑在某个地方创建一个单独的函数来包装try-catch并用它替换我的bfs :: exist调用,但我仍然不满意以这种方式使用try-catch是一个好主意.似乎我正在打开错过更重要和相关的特殊条件的大门.
我知道你可以为非抛出版本的函数重新编译boost,但我认为这并不能真正避免我的异常处理问题.
有没有人在使用可移动媒体驱动器之前遇到这个问题,如果是这样,你是如何克服它的?
可能重复:
在C中获取终端宽度?
在Linux和OS X上,我的shell报告$ COLUMNS具有终端窗口的宽度 - 调整窗口大小将调整此shell变量.
但是在我的C/C++程序中,getenv("COLUMNS")似乎没有找到变量.
有人有解释吗?或者让我的C++程序弄清楚它正在运行的终端的宽度的另一个建议(对于一些帮助消息自动换行)?