I have a bunch of SQL in a file, which creates the tables and so forth. The problem is that the .read command simply returns "can't open xxx" when I try to execute it. I've set the permissions to everybody read/write, but that didn't help. I can cat the file from the command line and see it fine.
This is under Mac OS 10.6.3.
Anybody have any idea here? Thanks!
Here's the source code in shell.c, where the sqlite3 utility executes the .read and tries to read the .sql file:
if( c=='r' && strncmp(azArg[0], "read", n)==0 && nArg==2 ){
FILE *alt = fopen(azArg[1], "rb");
if( alt==0 ){
fprintf(stderr,"can't open \"%s\"\n", azArg[1]);
}else{
process_input(p, alt);
fclose(alt);
}
}else
You can see that the utility will print "can't open xxx" only when the call to fopen fails. Pity they don't print errno for you, but this info should really help you narrow down the problem as not specific to sqlite.
You're either specifying the path wrong (try quoting it), you don't have permission, or the file really doesn't exist (meaning that there's something different in how you're using cat and .read, like the current directory is different).
Watch out for the ; at the end. .read does not like ;'s.
Related
so I am using zsh. I have a bunch of functions that move me around the place - like if I type "bin" anywhere - I go to ~/bin etc. I do this by hooking into the command_not_found_handler as so:
command_not_found_handler() {
if [ -f ~/bin/marked/$1 ]; then
directory=$(<~/bin/marked/$1)"
echo cd \"$directory\" >~/source_function
return 0
...
and this works fantastically - anywhere I am, I can just type marker blah - it creates a marker, and from then on anywhere I am, if I type blah it will just go back to that directory I marked.
Except.
I have "." in my path. (Yes I know you think I shouldn't do that)
and if there happens to be a "blah" file in the current directory - instead of going to the command not found handler - it tries to execute that, and its of course not an executable script, so I get "Permission Denied"
Is there any way to trap this permission denied, like I trap the command not found? It really hits me a lot with the word "scripts" - because I like typing scripts to take me to my personal scripts directory - but every program I write also has a scripts directory in the git repo for scripts related to that repository.
Aside from removing . from your path (which you don't want to do), I don't see a way to configure zsh to avoid executing (or attempting to execute) files that match the given command in the current directory. zsh has lots of options, but I don't see documentation describing any relevant ones, nor do I see source code support for one.
I make this claim based on reading the source code for zsh's handling in the execute() function at https://sourceforge.net/p/zsh/code/ci/master/tree/Src/exec.c. Here, when zsh sees dot (.) in the path, it attempts to execute a file by that name in that directory:
for (pp = path; *pp; pp++)
if (!(*pp)[0] || ((*pp)[0] == '.' && !(*pp)[1])) {
ee = zexecve(arg0, argv, newenvp);
if (isgooderr(ee, *pp))
eno = ee;
} else {
z = buf;
strucpy(&z, *pp);
*z++ = '/';
strcpy(z, arg0);
ee = zexecve(buf, argv, newenvp);
if (isgooderr(ee, *pp))
eno = ee;
}
After that, the execute() function reaches the code below and calls zerr(), which produces the "permission denied" error message:
if (eno)
zerr("%e: %s", eno, arg0);
else if (commandnotfound(arg0, args) == 0)
_realexit();
else
zerr("command not found: %s", arg0);
... and there is no logic in the code to intercept zsh's behavior in that case.
My best suggestion to achieve the desired result is to remove dot (.) from your path.
All, I am running the following script to load the data on to the Oracle Server using unix box and sqlldr. Earlier it gave me an error saying sqlldr: command not found. I added "SQLPLUS < EOF", it still gives me an error for unexpected end of file syntax error on line 12 but it is only 11 line of code. What seems to be the problem according to you.
#!/bin/bash
FILES='ls *.txt'
CTL='/blah/blah1/blah2/name/filename.ctl'
for f in $FILES
do
cat $CTL | sed "s/:FILE/$f/g" >$f.ctl
sqlplus ID/'PASSWORD'#SERVERNAME << EOF sqlldr SCHEMA_NAME/SCHEMA_PASSWORD control=$f.ctl data=$f EOF
done
sqlplus will never know what to do with the command sqlldr. They are two complementary cmd-line utilities for interfacing with Oracle DB.
Note NO sqlplus or EOF etc required to load data into a schema:
#!/bin/bash
#you dont want this FILES='ls *.txt'
CTL_PATH=/blah/blah1/blah2/name/'
CTL_FILE="$CTL_PATH/filename.ctl"
SCHEMA_NM=SCHEMA_NAME
SCHEMA_PSWD=SCHEMA_PASSWORD
for f in *.txt
do
# don't need cat! cat $CTL | sed "s/:FILE/$f/g" >"$f".ctl
sed "s/:FILE/$f/g" "$CTL_FILE" > "$CTL_PATH/$f.ctl"
#myBad sqlldr "$SCHEMA_NAME/$SCHEMA_PASSWORD" control="$CTL_PATH/$f.ctl" data="$f"
sqlldr $SCHEMA_USER/$SCHEMA_PASSWORD#$SERVER_NAME control="$CTL_PATH/$f.ctl" data="$f" rows=10000 direct=true errors=999
done
Without getting too philosophical, using assignments like FILES=$(ls *.txt) is a bad habit to get into. By contrast, for f in *.txt will deal correctly for files with odd characters in them (like spaces or other syntax breaking values). BUT the other habit you do want to get into is to quote all variable references (like $f), with dbl-quotes : "$f", OK? ;-) This is the otherside of protection for files with spaces etc embedded in them.
In the edit update, I've varibalized your CTL_PATH and CTL_FILE. I think I understand your intent, that you have 1 std CTL_FILE that you pass thru sed to create a table specific .ctl file (a good approach in my experience). Note that you don't need to use cat to send a file to sed, but your use to create a altered file via redirection (> $f.ctl) is very shell-like too.
In 2nd edit update, I looked here on S.O. and found an example sqlldr cmdline that has the correct syntax and have modified to work with your variable names.
To finish up,
A. Are you sure the Oracle Client package is installed on the machine
that you are running your script on?
B. Is the /path/to/oracle/client/tools/bin included in your working
$PATH?
C. try which sqlldr. If you don't get anything, either its not
installed or its not in the path.
D. If not installed, you'll have to get it installed.
E. Once installed, note the directory that contains the sqlldr cmd.
find / -name 'sqlldr*' will take a long time to run, but it will
print out the path you want to use.
F. Take the "path" part of what is returned (like
/opt/oracle/11.2/client/bin/ (but not the sqlldr at the end), and
edit script at 2nd line with
(Txt added to appease the S.O. Formatter ;-) )
export ORCL_PATH="/path/you/found/to/oracle/client"
export PATH="$ORCL_PATH:$PATH"
These steps should solve any remaining issues. If this doesn't work, see if there is someone where you work that understands your local computing environment that can help explain any missing or different steps.
IHTH
I have a document that is used by multiple people, and we have to continually check if the file is in use and by who.
I was wondering if there is anyway in R that I could obtain the status of an .xlsx file, if it is closed or open, and who has the file open.
I would then push this result to a HTML page which would refresh on a regular basis, this should then remove the need for the manual checking.
Here is a starting point you might consider. This option is using C code you can compile in with R Cmd and call from R.
In a file "islocked.c" paste this:
#include <stdio.h>
#include <share.h>
void testLock(int *locked, char **filename)
{
FILE *stream;
if( (stream = _fsopen( *filename, "wt", _SH_DENYWR )) != NULL ) {
fclose( stream );
*locked = 0;
} else {
*locked = 1;
}
}
Open a command prompt (windows | find | 'cmd')
Change into the folder you saved the file above
From your command prompt c:\ type the following
"Program File\R\R-3.1.2\bin\r" CMD SHLIB islocked.c
It shouldn't throw any errors or warnings and create a .o and .dll file as a result.
Now in R:
dyn.load('c:\pathtothe_c_file\islocked.dll')
result->.C('testLock', islocked=as.integer(0), filename="d:\tools\r\test.dll")
result$islocked
[1] 1
The dll is locked by R so this should return 1. Try the .o file and it should return 0. There is an API in Windows 7 and newer called IFileInUse which may return the process and possibly the user that has the file open that you might review if you need more information.
IsFileInUse API:
http://msdn.microsoft.com/en-us/library/windows/desktop/ee330722%28v=vs.85%29.aspx
A utility from Microsoft that runs on a command line you can shell to from R that may produce what you need, if you are able to install tools on the server:
http://technet.microsoft.com/en-us/sysinternals/bb896655.aspx
In Unix, it's possible to create a handle to an anonymous file by, e.g., creating and opening it with creat() and then removing the directory link with unlink() - leaving you with a file with an inode and storage but no possible way to re-open it. Such files are often used as temp files (and typically this is what tmpfile() returns to you).
My question: is there any way to re-attach a file like this back into the directory structure? If you could do this it means that you could e.g. implement file writes so that the file appears atomically and fully formed. This appeals to my compulsive neatness. ;)
When poking through the relevant system call functions I expected to find a version of link() called flink() (compare with chmod()/fchmod()) but, at least on Linux this doesn't exist.
Bonus points for telling me how to create the anonymous file without briefly exposing a filename in the disk's directory structure.
A patch for a proposed Linux flink() system call was submitted several years ago, but when Linus stated "there is no way in HELL we can do this securely without major other incursions", that pretty much ended the debate on whether to add this.
Update: As of Linux 3.11, it is now possible to create a file with no directory entry using open() with the new O_TMPFILE flag, and link it into the filesystem once it is fully formed using linkat() on /proc/self/fd/fd with the AT_SYMLINK_FOLLOW flag.
The following example is provided on the open() manual page:
char path[PATH_MAX];
fd = open("/path/to/dir", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
/* File I/O on 'fd'... */
snprintf(path, PATH_MAX, "/proc/self/fd/%d", fd);
linkat(AT_FDCWD, path, AT_FDCWD, "/path/for/file", AT_SYMLINK_FOLLOW);
Note that linkat() will not allow open files to be re-attached after the last link is removed with unlink().
My question: is there any way to re-attach a file like this back into the directory structure? If you could do this it means that you could e.g. implement file writes so that the file appears atomically and fully formed. This appeals to the my compulsive neatness. ;)
If this is your only goal, you can achieve this in a much simpler and more widely used manner. If you are outputting to a.dat:
Open a.dat.part for write.
Write your data.
Rename a.dat.part to a.dat.
I can understand wanting to be neat, but unlinking a file and relinking it just to be "neat" is kind of silly.
This question on serverfault seems to indicate that this kind of re-linking is unsafe and not supported.
Thanks to #mark4o posting about linkat(2), see his answer for details.
I wanted to give it a try to see what actually happened when trying to actually link an anonymous file back into the filesystem it is stored on. (often /tmp, e.g. for video data that firefox is playing).
As of Linux 3.16, there still appears to be no way to undelete a deleted file that's still held open. Neither AT_SYMLINK_FOLLOW nor AT_EMPTY_PATH for linkat(2) do the trick for deleted files that used to have a name, even as root.
The only alternative is tail -c +1 -f /proc/19044/fd/1 > data.recov, which makes a separate copy, and you have to kill it manually when it's done.
Here's the perl wrapper I cooked up for testing. Use strace -eopen,linkat linkat.pl - </proc/.../fd/123 newname to verify that your system still can't undelete open files. (Same applies even with sudo). Obviously you should read code you find on the Internet before running it, or use a sandboxed account.
#!/usr/bin/perl -w
# 2015 Peter Cordes <peter#cordes.ca>
# public domain. If it breaks, you get to keep both pieces. Share and enjoy
# Linux-only linkat(2) wrapper (opens "." to get a directory FD for relative paths)
if ($#ARGV != 1) {
print "wrong number of args. Usage:\n";
print "linkat old new \t# will use AT_SYMLINK_FOLLOW\n";
print "linkat - <old new\t# to use the AT_EMPTY_PATH flag (requires root, and still doesn't re-link arbitrary files)\n";
exit(1);
}
# use POSIX qw(linkat AT_EMPTY_PATH AT_SYMLINK_FOLLOW); #nope, not even POSIX linkat is there
require 'syscall.ph';
use Errno;
# /usr/include/linux/fcntl.h
# #define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links. */
# #define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */
# #define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */
unless (defined &AT_SYMLINK_NOFOLLOW) { sub AT_SYMLINK_NOFOLLOW() { 0x0100 } }
unless (defined &AT_SYMLINK_FOLLOW ) { sub AT_SYMLINK_FOLLOW () { 0x0400 } }
unless (defined &AT_EMPTY_PATH ) { sub AT_EMPTY_PATH () { 0x1000 } }
sub my_linkat ($$$$$) {
# tmp copies: perl doesn't know that the string args won't be modified.
my ($oldp, $newp, $flags) = ($_[1], $_[3], $_[4]);
return !syscall(&SYS_linkat, fileno($_[0]), $oldp, fileno($_[2]), $newp, $flags);
}
sub linkat_dotpaths ($$$) {
open(DOTFD, ".") or die "open . $!";
my $ret = my_linkat(DOTFD, $_[0], DOTFD, $_[1], $_[2]);
close DOTFD;
return $ret;
}
sub link_stdin ($) {
my ($newp, ) = #_;
open(DOTFD, ".") or die "open . $!";
my $ret = my_linkat(0, "", DOTFD, $newp, &AT_EMPTY_PATH);
close DOTFD;
return $ret;
}
sub linkat_follow_dotpaths ($$) {
return linkat_dotpaths($_[0], $_[1], &AT_SYMLINK_FOLLOW);
}
## main
my $oldp = $ARGV[0];
my $newp = $ARGV[1];
# link($oldp, $newp) or die "$!";
# my_linkat(fileno(DIRFD), $oldp, fileno(DIRFD), $newp, AT_SYMLINK_FOLLOW) or die "$!";
if ($oldp eq '-') {
print "linking stdin to '$newp'. You will get ENOENT without root (or CAP_DAC_READ_SEARCH). Even then doesn't work when links=0\n";
$ret = link_stdin( $newp );
} else {
$ret = linkat_follow_dotpaths($oldp, $newp);
}
# either way, you still can't re-link deleted files (tested Linux 3.16 and 4.2).
# print STDERR
die "error: linkat: $!.\n" . ($!{ENOENT} ? "ENOENT is the error you get when trying to re-link a deleted file\n" : '') unless $ret;
# if you want to see exactly what happened, run
# strace -eopen,linkat linkat.pl
Clearly, this is possible -- fsck does it, for example. However, fsck does it with major localized file system mojo and will clearly not be portable, nor executable as an unprivileged user. It's similar to the debugfs comment above.
Writing that flink(2) call would be an interesting exercise. As ijw points out, it would offer some advantages over current practice of temporary file renaming (rename, note, is guaranteed atomic).
Kind of late to the game but I just found http://computer-forensics.sans.org/blog/2009/01/27/recovering-open-but-unlinked-file-data which may answer the question. I haven't tested it, though, so YMMV. It looks sound.
Minor problem, nevertheless irritating : Is there a way to avoid the following message from appearing each time I make a query :
-- Loading resources from /Users/ThG/.sqliterc
As a stupid workaround, this works:
<. sqlite your_sqlite.db 'select * from your_table'
This is because the current code does this:
if( stdin_is_interactive ){
utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
}
Forcing a stdin redirect thwarts this due to this piece of code:
stdin_is_interactive = isatty(0);
This works as well:
sqlite -batch your_sqlite.db 'select * from your_table'
due to this piece of code:
}else if( strcmp(z,"-batch")==0 ){
/* Need to check for batch mode here to so we can avoid printing
** informational messages (like from process_sqliterc) before
** we do the actual processing of arguments later in a second pass.
*/
stdin_is_interactive = 0;
}
but it's longer, so kind of defeats the purpose.
I know that this question is PRETTY old now, but simply deleting '/Users/ThG/.sqliterc' should solve the problem. '.sqliterc' is a configuration file for sqlite's interactive command line front-end. If you don't spend a lot of time in there, you won't miss the file.
That resource msg comes out on stderr, and it's followed by a blank line, so you could get rid of it with something like this (wrapped up in a script file of its own):
#!/bin/bash
sqlite3 -init /your/init/file /your/sqlite3/file.db "
your
SQL
cmds
" 2>/dev/null | sed -e1d
When using sqlite in shell scripts, you usually don't even want your ~/.sqliterc to be loaded at all. This works well for me:
sqlite3 -init <(echo)
Explanation:
-init specifies the file to load instead of ~/.sqliterc.
<(echo) uses Process Substitution to provide a path to a temporary empty file.
A bit late but #levant pied almost had the solution, you need to pass an additional -interactive to silence the --loading resources from.
$ sqlite3 -batch -interactive
SQLite version 3.31.1 2020-01-27 19:55:54
Enter ".help" for usage hints.
sqlite> .q
You can simply rename your config file to disable the warning. And revert the rename to keep the configuration after use.
I use the following:
#suppress default configuration warnings
mv $HOME/.sqliterc $HOME/.backup.sqliterc
# sqlite3 scripts...
#revert
mv $HOME/.backup.sqliterc $HOME/.sqliterc