I want to change the behaviour of my ESP module if some of my parameter was changed and then was restarted. I mean something like this.
if (????) then
print ("default value") else
print ("modified value") end
First I thought of writing a flag into a file, but it causes error during boot if it is not existing yet.
Any better idea?
If you want to store values beyond reboot you have to store them in some non-volatile memory. So using a file is a good way as you already suggested.
Unfortunately you did not provide the error message you get when it is not existing yet and you did not say if the flag or the file does not exist.
What you have to do is handling the error. So if your file does not exist ask the user to create a new one or create a file with default content from your program.
Same goes with the flag. If the file does not contain a flag yet, use a default value or ask the user to give one.
It's not bad or wrong to get errors as long learn from them or handle them properly.
io.open(filename[,mode]) returns nil plus an error message in case of an error.
So simply do something like:
local fileName = "C:\\superfile.txt"
local fileHandle, errorMsg = io.open(fileName)
if not fileHandle then
print("File access error: ", errorMsg)
-- add some error handling here
end
So in case you don't have that file you'll get
File access error: C:\superfile.txt: No such file or directory
Related
I'm attempting to constantly read and parse a log file (Minecraft log file) by using io.popen in tandem with Ubuntu's tail command so that I can send some messages upon certain events.
Now, I have mostly everything working here, except one small issue. After a while of reading, the entire program just freezes.
Here is the relevant code:
-- Open the tail command, return a file handle for it.
local pop = io.popen(config.listen_command)
-- Simply read a single line, I've pulled this into its own
-- function so that if this ever needs changing I can do so
-- easily.
local function get_line()
logger:log(4, "READ LINE")
return pop:read("*l")
end
-- For each line in the log file, check if it matches any
-- of a list of patterns, return the matches and the
-- pattern information if so.
local function match_line()
local line = get_line()
logger:log(4, "Line: %s", line)
-- This all works, and I've tested that it's not freezing
-- here. I've just included it for completion of the call
-- -stack.
for event_type, data in pairs(config.message_patterns) do
for event_name, pattern in pairs(data) do
local matches = {line:match(pattern)}
if matches[1] then
return event_type, event_name, matches
end
end
end
end
-- The main loop, simply read a line and send a message
-- if there was a match.
logger:log(4, "Main loop begin.")
while true do
local event_type, event_name, matches = match_line()
-- ...
-- The rest of the code here is not relevant.
config.listen_command = "tail -F --lines=1 latest.log"
The issue is in the get_line function. After a while of reading the log file, it completely freezes on the pop:read("*l"). It prints the READ LINE message, but never prints the Line: <whatever data here> line.
This is a really strange issue that I've been getting really confused about. I've tried swapping to different distributions of Lua (Luvit, LuaJIT, Lua) and a very large amount of debugging, changing small things, rerunning, ... But I cannot think of anything that'd be causing this.
Perhaps there's something small I've missed.
So my question here is this: Why is pop:read("*l") freezing, even though more data is being outputted to the logfile? Is there a way to fix this? Perhaps to detect if the next read will freeze indefinitely, so I can try closing the popen'ed file and re-open it (or to preferably stop it happening altogether?)
I am trying to make a fivem server and have been able to configure esx_addonaccount once before, but now that I have needed to restart my project it is not seeming to work. My database is considered fine, and I am running a completely vanilla install minus the esx framework plugins and esx_addonaccount, which is the problem. This occurs when I load into the server anytime.
Error running system event handling function for resource esx_addonaccount: citizen:/scripting/lua/scheduler.lua:41: Failed to execute thread: #esx_addonaccount/server/main.lua:87: attempt to index a nil value (local 'xPlayer')
stack traceback:
#esx_addonaccount/server/main.lua:87: in upvalue 'handler'
citizen:/scripting/lua/scheduler.lua:219: in function <citizen:/scripting/lua/scheduler.lua:218>
stack traceback:
[C]: in function 'error'
citizen:/scripting/lua/scheduler.lua:41: in field 'CreateThreadNow'
citizen:/scripting/lua/scheduler.lua:218: in function <citizen:/scripting/lua/scheduler.lua:182>
Please help!!
#esx_addonaccount/server/main.lua:87: attempt to index a nil value (local 'xPlayer')
Above is a line from your error. It basically says that in resource esx_addonaccount, in folder ./server/, in file main.lua, in line 87 you are trying to access xPlayer variable, but in this specific case it equals nil. This means that either you have not initialized ESX correctly or somehow xPlayer is not existing - eg. player with given ID doesn't exist.
The best bet would be to check the whole 'path' of this variable - where is it created, initialized and populated with data.
ESX resources should work out of the box, so if it doesn't, then try to follow the installation instructions in their README files or on github and see if you did everything to correctly install them on your server.
I was moving some map files, and I rebooted my server (FiveM) and when I called it again it started to give this problem, I undo everything I did, I put the old files again, but the error kept happening. And I do not know what to do to solve it.
I threw all the changed files back to normal, but it did not solve anything.
local cfg = module("cfg/blips_markers")
-- add additional static blips/markers
AddEventHandler("vRP:playerSpawn",function(user_id, source, first_spawn)
if first_spawn then
for k,v in pairs(cfg.blips) do
vRPclient.addBlip(source,{v[1],v[2],v[3],v[4],v[5],v[6]})
end
for k,v in pairs(cfg.markers) do
vRPclient.addMarker(source,{v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]})
end
end
end)
Inside the server the blip_markes are gone and some player data too, because of that.
A quick debug would be to assign cfg the value of an integer, if your problem solves, you know that something is wrong with module("cfg/blips_markers"). However, please provide the code associated with module("cfg/blips_markers").
I have been trying to download a file using Net::SFTP and it keeps getting an error.
The file is partially downloaded, and is only 2.1 MB, so it's not a huge file. I removed the loop over the files and even tried just downloading the one file and got the same error:
yml = YAML.load_file Rails.root.join('config', 'ftp.yml')
Net::SFTP.start(yml["url"], yml["username"], password: yml["password"]) do |sftp|
sftp.dir.glob(File.join('users', 'import'), '*.csv').each do |f|
sftp.download!(File.join('users', 'import', f.name), Rails.root.join('processing_files', 'download_files', f.name), read_size: 1024)
end
end
NoMethodError: undefined method `close' for #<Pathname:0x007fc8fdb50ea0>
from /[my_working_ap_dir]/gems/net-sftp-2.1.2/lib/net/sftp/operations/download.rb:331:in `on_read'
I have prayed to Google all I can and am not getting anywhere with it.
Rails.root returns a Pathname object, but it looks like the sftp code doesn't check to see whether it got a Pathname or a File handle, it just runs with it. When it runs into entry.sink.close it crashes because Pathnames don't implement close.
Pathnames are great for manipulating paths to files and directories, but they're not substitutes for file handles. You could probably tack on to_s which would return a string.
Here's a summary of the download call from the documentation that hints that the expected parameters should be a String:
To download a single file from the remote server, simply specify both the
remote and local paths:
downloader = sftp.download("/path/to/remote.txt", "/path/to/local.txt")
I suspect that if I dig into the code it will check to see whether the parameters are strings, and, if not, assumes that they are IO handles.
See ri Net::SFTP::Operations::Download for more info.
Here's an excerpt from the current download! code, and you can see how the problem occurred:
def download!(remote, local=nil, options={}, &block)
require 'stringio' unless defined?(StringIO)
destination = local || StringIO.new
result = download(remote, destination, options, &block).wait
local ? result : destination.string
end
local was passed in as a Pathname. The code checks to see if there's something passed in, but not what that is. If nothing is passed in it assumes it's something with IO-like features, which is what StringIO provides for the in-memory caching.
Apparently you can't use Rails.root.join, which was causing the problem. It is really stupid though because it would download part of the file.
Changed:
sftp.download!(File.join('users', 'import', f.name), Rails.root.join('processing_files', 'download_files', f.name))
To:
sftp.download!(File.join('users', 'import', f.name), File.join('processing_files', 'download_files', f.name))
argument remote can be a Pathname object while argument local when set should be a String or else an object that responds to #write method.
Below is the working code
local_stringified_path = Rails.root.join('processing_files', f.name).to_s
sftp.download!(Pathname.new('/users/import'), local_stringified_path)
For all those curious minds please read below to understand this behaviour..
The issue NoMethodError: undefined method close' for #<Pathname:0x007fc8fdb50ea0> happens exactly here
in the #on_read method and below is the code snippet of the concerned statements.
if response.eof?
update_progress(:close, entry)
entry.sink.close # ERRORED OUT LINE.. ideally when eof, file IO handler is supposed to be closed
WHAT IS entry.sink ?
We know already that #download! methods takes two args as below
sftp.download!(remote, local)
The given args remote and local is converted to an Entry object here
[Entry.new(remote, local, recursive?)]
and Entry is a nothing but a Struct here
Entry = Struct.new(:remote, :local, :directory, :size, :handle, :offset, :sink)
okay then what is sink attribute? we will jump to that right away..
Once the concerned remote file is open to be read, the #on_open method updates this sink attribute with a File handler here.
Find the snippet below,
entry.sink = entry.local.respond_to?(:write) ? entry.local : ::File.open(entry.local, "wb")
This actually happens only when given local path object doesn't implement it's own #write method In our scenario, Pathname objects does respond to write
Below are some snippets of the console outputs, I inspected in between multiple download chunk calls while debugging this.. which shows the entry and entry.sink displaying the above discussed objects.
Here I chose my remote to be a Pathname object and local to be String path which returns proper value for the entry.sink and there by downloading successfully..
0> entry
=> #<struct Net::SFTP::Operations::Download::Entry remote=#<Pathname:214010463.xml>, local="214010463.xml", directory=nil, size=nil, handle="1", offset=32000, sink=#<File:214010463.xml>>
0> entry.sink
=> #<File:214010463.xml>
I'm trying to script a lua file to check if a certain file is open. Then I want it to close that file if it is open. I know how to check if the file exist but I need to know how to check if the file is open, meaning the file is running.
Lua, like C, C++, and pretty much every other language, can only close files that it opens itself. You cannot close files open by other people (not with standard Lua calls); this would be incredibly rude.
So you can't test to see if a file is opened by someone else. Nor can you close their file. There may be system API calls you could make to do this, but you would have to give Lua scripts access to those APIs yourself. Lua's standard libraries can't do this.
Sounds like you want to check which if any programs have a given file open.
first thing that comes to mind is parsing the output of lsof on linux.
fd = io.popen("lsof path/to/my/file")
fileopened = (#fd:read("a*") > 0)
Kind of a hacky way to do it, but it works:
processname = "process_name_here.exe"
filedata = io.popen("tasklist /NH /FO CSV /FI \"IMAGENAME eq "..processname.."\"")
output = filedata:read()
filedata:close()
if output ~= "INFO: No tasks are running which match the specified criteria." then
-- Program is running. Close the program
os.execute("taskkill -im "..processname)
else
-- Program is not running
end
Just make sure to replace "process_name_here.exe" with the process name that shows up in task manager
Alternatively you can just use this to close it without checking if it was actually running:
os.execute("taskkill -im process_name_here.exe")