Print to a shared network printer using GO - windows

I have a printer shared on network, to which I am able to print from command line using
echo hello > \\PSNHP\PRN
or
copy /b hello.txt \\PSNHP\PRN
Idea from this link
https://supportcommunity.zebra.com/s/article/Print-RAW-File-From-CMD?language=en_US
I like this because that way I do not need to install any driver on windows
I am trying to do the same from go
socket, err = os.OpenFile("\\\\"+comp+"\\PRN", os.O_WRONLY, os.ModeNamedPipe)
//or
socket, err = os.Open("\\\\"+comp+"\\PRN")
However, I am getting this error
open \\PSNHP\PRN: The system cannot find the file specified.
So, I am confused, is a network printer a file or not, how does the command prompt understand the stream redirection.
I think this question in c# has the same roots, I am not happy with the proposed answer, as I do not have direct network access to the printer
Send text file directly to network printer

I've narrowed it down with ProcMon from sysinternals, compared the differences and figured it out.
Not working
Desired Access: Generic Write, Read Attributes
Disposition: Open
Options: Synchronous IO Non-Alert, Non-Directory File
Attributes: R
ShareMode: Read, Write
AllocationSize: n/a
Working
Desired Access: Generic Write, Read Attributes
Disposition: OverwriteIf
Options: Synchronous IO Non-Alert, Non-Directory File
Attributes: N
ShareMode: Read
AllocationSize: 0
OpenResult: Created
Notice the overwriteif, well the sytem cannot find the file, but it could be created, and then the spooler on the other computer, will print it instead of actually creating the file.
My modified go code
socket, err := os.OpenFile("\\\\PSNHP\\PRN", os.O_WRONLY|os.O_CREATE, 0)
fmt.Println(err)
socket.Write([]byte("hello\n"))
socket.Close()

Related

Cloud Run Golang container issue/missunderstanding

I'm trying to do a report of all the objects in all the projects we have in Cloud Storage of our Org. I'm using this repo from the Google Professionnal Services as it's doing exactly what we want: https://github.com/GoogleCloudPlatform/professional-services/tree/main/tools/gcs2bq
We want to use containers instead of just the go code on a Cloud Function for portability mainly.
Locally everything is good and the program behave as expected but when I try in Cloud Run things get tricky. From what I understand, the go part needs to listen to a port, which I added at the beginning of the main so the container can be deployed, which it is:
// Determine port for HTTP service
port := os.Getenv("PORT")
if port == "" {
port = "8080"
log.Printf("defaulting to port %s", port)
}
Start HTTP server.
log.Printf("listening on port %s", port)
if err := http.ListenAndServe(":"+port, nil); err != nil {
log.Fatal(err)
}
But as you can see in the repo, the first file called is the run.sh one. Which set environment variables and then call the main.go. It sucessfully complete it's task, which is get all the size of the different files. But after that the run.sh doesnt "resume" and go to the part where it uploads the data in a BigQuery table, which locally work.
Here is the part in the run.sh file where I have a problem. Note : I don't have errors from executing the ./gcs2bq Note 2 : Every environment variable has a correct value
./gcs2bq $GCS2BQ_FLAGS || error "Export failed!" 2 <- doesnt get past this line
gsutil mb -p "${GCS2BQ_PROJECT}" -c standard -l "${GCS2BQ_LOCATION}" -b on "gs://${GCS2BQ_BUCKET}" || echo "Info: Storage bucket already exists: ${GCS2BQ_BUCKET}"
gsutil cp "${GCS2BQ_FILE}" "gs://${GCS2BQ_BUCKET}/${GCS2BQ_FILENAME}" || error "Failed copying ${GCS2BQ_FILE} to gs://${GCS2BQ_BUCKET}/${GCS2BQ_FILENAME}!" 3
bq mk --project_id="${GCS2BQ_PROJECT}" --location="${GCS2BQ_LOCATION}" "${GCS2BQ_DATASET}" || echo "Info: BigQuery dataset already exists: ${GCS2BQ_DATASET}"
bq load --project_id="${GCS2BQ_PROJECT}" --location="${GCS2BQ_LOCATION}" --schema bigquery.schema --source_format=AVRO --use_avro_logical_types --replace=true "${GCS2BQ_DATASET}.${GCS2BQ_TABLE}" "gs://${GCS2BQ_BUCKET}/${GCS2BQ_FIL$
error "Failed to load gs://${GCS2BQ_BUCKET}/${GCS2BQ_FILENAME} to BigQuery table ${GCS2BQ_DATASET}.${GCS2BQ_TABLE}!" 4
gsutil rm "gs://${GCS2BQ_BUCKET}/${GCS2BQ_FILENAME}" || error "Failed deleting gs://${GCS2BQ_BUCKET}/${GCS2BQ_FILENAME}!" 5
rm -f "${GCS2BQ_FILE}"
I'm kinda new to containers and Cloud Run and even after reading projects and documentation, I'm not sure what I'm doing wrong, Is it normal that the .sh is "stuck" when calling the main.go? I can provide more details/explaination if needed.
Okay so for anyone who encounter similar situation this is how I made it work for me.
The container isn't supposed to stop so no exit, it will just go back to the main function.
That means that when I called executable it just looped and never exited and completed the task. So the solution here is to "recode" everything past the call in golang directly into the main.go
Here the run.sh is then useless so I used another .go file that listen for http request and then call the code that gather data and send it to Bigquery.

Why Logrus writes logs to Linux logs?

I use Logrus library to write my golang logs to file. The problem is that logrus also writes the logs to Linux system logs. Here is my log output in log configs.
log.SetOutput(os.Stderr)
I do not want Logrus to write application logs to Linux system logs. Any idea about solving this problem?
To write output to file, you can set output to a file handler.
file, err := os.OpenFile(filename, os.O_WRONLY | os.O_CREATE, 0755)
if err != nil {
// handle error
}
logrus.SetOutput(f)
In case you want to introduce more advanced logic to handle the output, you can use this library Lumberjack as log output

Is it possible to log the output of a uboot command into a file from u-boot prompt?

I am working with an embedded board which supports u-boot.
I am trying to write and read the emmc device connected to the board,
After read, i need to have a look at the contents and compare it with the data that I have written to it.
Is there a way I can log the output of the a u-boot command, when I read a block from eMMC and store it in an address and try to view the contents of
it using:
mmc read 0x10700000 133120 1
mm.l 0x10700000
into a file and then can store the file in an emmc partition or a tftp server ?
Thank you for your time,
Nishad
The save command can be used to write memory to a file.
save file to a filesystem
save <interface> <dev[:part]> <addr> <filename> bytes [pos]
- Save binary file 'filename' to partition 'part' on device
type 'interface' instance 'dev' from addr 'addr' in memory.
'bytes' gives the size to save in bytes and is mandatory.
'pos' gives the file byte position to start writing to.
If 'pos' is 0 or omitted, the file is written from the start.
Of cause this requires the file system to be writable. For FAT this implies building with CONFIG_FAT_WRITE=y.

golang exec incorrect behavior

I'm using following code segment to get the XML definition of a virtual machine running on XEN Hypervisor. The code is trying to execute the command virsh dumpxml Ubutnu14 which will give the XML of the VM named Ubuntu14
virshCmd := exec.Command("virsh", "dumpxml", "Ubuntu14")
var virshCmdOutput bytes.Buffer
var stderr bytes.Buffer
virshCmd.Stdout = &virshCmdOutput
virshCmd.Stderr = &stderr
err := virshCmd.Run()
if err != nil {
fmt.Println(err)
fmt.Println(stderr.String())
}
fmt.Println(virshCmdOutput.String())
This code always goes into the error condition for the given domain name and I get the following output.
exit status 1
error: failed to get domain 'Ubuntu14'
error: Domain not found: no domain with matching name 'Ubuntu14'
But if I run the standalone command virsh dumpxml Ubuntu14, I get the correct XML definition.
I would appreciate if someone could give me some hints on what I'm doing wrong. My host machine is Ubuntu-16.04 and golang version is go1.6.2 linux/amd64
I expect you are running virsh as a different user in these two scenarios, and since you don't provide any URI, it is connecting to a different libvirtd instance. If you run virsh as non-root, then it'll usually connect to qemu:///session, but if you run virsh as root, then it'll usually connect to qemu:///system. VMs registered against one URI, will not be visible when connecting to the other URI.
BTW, if you're using go, you'd be much better off using the native Go library bindings for libvirt instead of exec'ing virsh. Your "virsh dumpxml" invokation is pretty much equivalent to this:
import (
"github.com/libvirt/libvirt-go"
)
conn, err := libvirt.NewConnect("qemu:///system")
dom, err := conn.LookupDomainByName("Ubuntu14")
xml, err := dom.GetXMLDesc(0)
(obviously do error handling too)

How to bypass permission denied error?

The following example writes a point shapefile to disc. However, I get an error when the script tries to write a shapefile to C:/. I am able to write to a external hard drive though (G:/). The following is the error I receive in R:
Error in file(out.name, "wb") : cannot open the connection In
addition: Warning message: In file(out.name, "wb") : cannot open file
'c:/test.shp': Permission denied
How can I bypass or resolve this error?
# available from: cran.r-project.org/web/packages/shapefiles/shapefiles.pdf
# Samples of using the convert.to.shapefile function to write out simple shapefiles
# from basic R data.frames
require(shapefiles)
require(maptools)
dd <- data.frame(Id=c(1,2),X=c(3,5),Y=c(9,6))
ddTable <- data.frame(Id=c(1,2),Name=c("Item1","Item2"))
ddShapefile <- convert.to.shapefile(dd, ddTable, "Id", 1)
write.shapefile(ddShapefile, "C:/test", arcgis=T)
shape <- readShapePoints("C:/test")
plot(shape)
Simple answer, do not write to the root-level directory of the system volume.
There are a few good reasons to create files/directories at the root of C:, but this isn't one of them. Use C:/Temp/test instead.

Resources