swift "print" 未出现在 STDOut 中,但当 运行 在 docker 中时,第 3 方 c 库日志会出现在 ECS 上
swift "print" doesn't appear in STDOut but 3rd party c library logs do when running in docker on ECS
所以在本地通过 xcode
进行开发或使用 SPM
编译时,控制台日志会按预期显示。
即 SPM
在本地一切正常
swift build --configuration release
.build/release/Myapp # prints to console
但是当我 运行 通过 ECS 上的 docker 容器 运行 执行时(linux 我想),我没有看到生成的日志我的 Swift 代码,但我确实看到 stderr 被第 3 方库打印(即 libssl 正在打印错误)以及 shell 启动应用程序时的日志
例如:
Docker 文件
FROM swift
WORKDIR /app
COPY Package.swift ./
COPY Sources ./Sources
COPY Tests ./Tests
RUN swift package clean
RUN swift build --configuration release
RUN chmod +x start.sh
CMD ["start.sh"] # just a wrapper to see if "echo" works
在start.sh
# prints as expected
echo "hi this will print"
# nothing in the executable will print though
.build/release/MyApp
我不确定为什么它没有出现在标准输出中,但您可以这样做:
import Foundation
internal struct FileHandleOutputStream: TextOutputStream {
private let fileHandle: FileHandle
let encoding: String.Encoding
init(_ fileHandle: FileHandle, encoding: String.Encoding = .utf8) {
self.fileHandle = fileHandle
self.encoding = encoding
}
mutating func write(_ string: String) {
if let data = string.data(using: encoding) {
fileHandle.write(data)
}
}
}
internal var STDERR = FileHandleOutputStream(.standardError)
internal var STDOUT = FileHandleOutputStream(.standardOutput)
这允许你做:
print("error message", to: &STDERR)
打印到标准错误。
我知道这只是一种解决方法,但总比没有好。
有同样的问题,我提交了雷达,苹果回答:
When piped to another process print is buffered, so no characters appear until the buffer is filled up. (When piped to the terminal we only buffer until we hit a newline.)
You can get the behavior you want by calling setbuf(stdout, nil)
once at startup:
import Darwin
setbuf(stdout, nil)
使用此代码,您将覆盖所有打印,因此它将在 Linux 和 Mac Xcode 上工作。
我使用了@sam 的回复并添加了覆盖 print
import Foundation
internal var STDERR = FileHandleOutputStream(.standardError)
internal var STDOUT = FileHandleOutputStream(.standardOutput)
internal struct FileHandleOutputStream: TextOutputStream {
private let fileHandle: FileHandle
let encoding: String.Encoding
init(_ fileHandle: FileHandle, encoding: String.Encoding = .utf8) {
self.fileHandle = fileHandle
self.encoding = encoding
}
mutating func write(_ string: String) {
if let data = string.data(using: encoding) {
fileHandle.write(data)
}
}
}
///
/// Override of the print so it can work with Linux and MAC
///
public func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
let output = items.map { "\([=10=])" }.joined(separator: separator)
#if os(Linux)
print(output, to: &STDERR)
#else
Swift.print(output, terminator: terminator)
#endif
}
所以在本地通过 xcode
进行开发或使用 SPM
编译时,控制台日志会按预期显示。
即 SPM
在本地一切正常
swift build --configuration release
.build/release/Myapp # prints to console
但是当我 运行 通过 ECS 上的 docker 容器 运行 执行时(linux 我想),我没有看到生成的日志我的 Swift 代码,但我确实看到 stderr 被第 3 方库打印(即 libssl 正在打印错误)以及 shell 启动应用程序时的日志
例如:
Docker 文件
FROM swift
WORKDIR /app
COPY Package.swift ./
COPY Sources ./Sources
COPY Tests ./Tests
RUN swift package clean
RUN swift build --configuration release
RUN chmod +x start.sh
CMD ["start.sh"] # just a wrapper to see if "echo" works
在start.sh
# prints as expected
echo "hi this will print"
# nothing in the executable will print though
.build/release/MyApp
我不确定为什么它没有出现在标准输出中,但您可以这样做:
import Foundation
internal struct FileHandleOutputStream: TextOutputStream {
private let fileHandle: FileHandle
let encoding: String.Encoding
init(_ fileHandle: FileHandle, encoding: String.Encoding = .utf8) {
self.fileHandle = fileHandle
self.encoding = encoding
}
mutating func write(_ string: String) {
if let data = string.data(using: encoding) {
fileHandle.write(data)
}
}
}
internal var STDERR = FileHandleOutputStream(.standardError)
internal var STDOUT = FileHandleOutputStream(.standardOutput)
这允许你做:
print("error message", to: &STDERR)
打印到标准错误。
我知道这只是一种解决方法,但总比没有好。
有同样的问题,我提交了雷达,苹果回答:
When piped to another process print is buffered, so no characters appear until the buffer is filled up. (When piped to the terminal we only buffer until we hit a newline.)
You can get the behavior you want by calling
setbuf(stdout, nil)
once at startup:
import Darwin
setbuf(stdout, nil)
使用此代码,您将覆盖所有打印,因此它将在 Linux 和 Mac Xcode 上工作。 我使用了@sam 的回复并添加了覆盖 print
import Foundation
internal var STDERR = FileHandleOutputStream(.standardError)
internal var STDOUT = FileHandleOutputStream(.standardOutput)
internal struct FileHandleOutputStream: TextOutputStream {
private let fileHandle: FileHandle
let encoding: String.Encoding
init(_ fileHandle: FileHandle, encoding: String.Encoding = .utf8) {
self.fileHandle = fileHandle
self.encoding = encoding
}
mutating func write(_ string: String) {
if let data = string.data(using: encoding) {
fileHandle.write(data)
}
}
}
///
/// Override of the print so it can work with Linux and MAC
///
public func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
let output = items.map { "\([=10=])" }.joined(separator: separator)
#if os(Linux)
print(output, to: &STDERR)
#else
Swift.print(output, terminator: terminator)
#endif
}