1

У меня есть программа, которая работает на виртуальной машине Windows VirtualBox, и хранит данные в определенной папке. Я хотел бы создать что-то вроде символической ссылки из этой папки на каталог на сервере Linux, но я не смог найти работающее решение. Я попытался сопоставить структуру папок Linux с буквой диска, а затем создать переход из «исходной» папки Windows в ту, которая сопоставлена с буквой диска, но Windows не позволяет мне завершить ссылку. Я также попытался подключить каталог Linux с помощью SFTP, но это тоже не сработало.

2 ответа2

1

Если вы не можете изменить папку в настройках программы, то, вероятно, вы ничего не можете сделать, кроме создания цели iSCSI на вашем ПК с Linux (цель файла, вероятно, для сохранения ваших разделов в целости) и использования инициатора iSCSI на виртуальной машине Windows для подключиться к нему (инициатор MS iSCSI, инициатор StarWind iSCSI).

В качестве альтернативы можно отредактировать программу в шестнадцатеричном формате и указать ее на подключенном сетевом диске, но это требует определенных навыков.

ОБНОВЛЕНИЕ: я нашел решение, которое выглядит многообещающим и не требует вмешательства в iSCSI: есть ли способ сопоставить UNC-путь с локальной папкой в Windows 2003? , Похоже, что mklink может отображать сетевые ресурсы (позор мне, я должен был это проверить), и в случае неудачи вы можете попробовать Symbolic Link Driver для Windows XP.

1

Вот что я сделал.

Сначала я установил SAMBA на коробку Linux и поделился дисками, которые хотел использовать. (Это целая другая тема, но вы можете найти множество описаний того, как это сделать.)

Затем в окне Windows я создал класс Python 3 ниже для создания ссылок.

Он также может быть использован для создания ссылок на общие ресурсы Windows.

Но короткий ответ - создайте общие ресурсы в окне linux и используйте mklink в командной строке для создания символической ссылки.

Предупреждение: этот код предназначен для проверки концепции. Это работа в процессе и является неполной. Я не утверждаю, что это лучший код или даже хороший код.

"""    
@Author: J. Michael Adams

Please cite the author's name if you use any of this code.

Creates symlinks for share folders

It places all the symlinks in a local folder. The test code defines that folder
as C:\share_symlinks.

NOTE -
This program uses the "mklink" command of the Windows command shell.
That command normally requires elevated administrator privilege.
That requirement can be changed using the "secpol.msc" console under
Security Settings > Local Policies > User Rights Assignment > create symbolic links

It pipes in a list of shares from the "net view" command.

Each output line from net view has this format: share-name "Disk" other-info
If it does not contain " Disk ", then it does not have a share name.

We want to create a symlink for each share.
The links will be created in a particular directory.

You can specify a list of share names that will be excluded - that is, they will
not be linked to. A name can can contain wildcards.

Any share name that matches a name in the exclude list will be ignored.
"""

#TODO: create a config file: excludes, link_dir, remote_drive, notify always, email parms
#TODO: check the permission level
#TODO: check the value of comspec
#TODO: remove obsolete links - links that have the proper remote_drive
#TODO: create an email object for notification
#TODO: create an exception that emails a notification

import os
import subprocess

class LinkManager(object):

    def __init__(self, remote_drive):
        self.remote_drive = remote_drive

        self.share_paths = {}  # share_paths[share name] => full path to share
        self.new_links = {}
        self.all_links = {}
        self.bad_links = {}

    def get_shares(self, excludes=None):

        """ returns a dict: key = share name, value = full path to the share

        """

        import fnmatch

        if type(excludes) is not list:
            if excludes is None:
                excludes = []
            elif type(excludes) is str:
                excludes = [excludes]
            else:
                raise Exception

        # Always exclude shares that end with '$'. These are administrative shares in Windows.
        excludes.append('*$')
        # We want to ignore case when we compare strings in the excludes list.
        # So we'll convert all share names to lower case.
        excludes = [x.lower() for x in excludes]

        ## call net view for the share drive. This might produce "access denied".
        # http://stackoverflow.com/questions/3005437/windowserror-error-5-access-is-denied
        cmd = "net view {} /all".format(remote_drive)

        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                shell=True, universal_newlines=True)
        (out, err) = proc.communicate()

        if err:
            return out, err  #TODO: should be an exception

        ## get the output of the command and parse the share names
        # we'll convert all lines to lower case.
        # Since this is Windows, file names are case insensitive.
        # We do this so we can compare to the lower case names in the exclude list.
        lines = out.lower().split('\n')

        for line in lines:

            # search for " disk " surrounded by a space, in case "disk" is a share name.
            if " disk " not in line:
                continue

            share = line.split(' disk ')[0].strip()

            # Check the share name against the exclude list.
            # The list can have names with wildcards ('*' and '?'),
            # so we'll use fnmatch() to check it.
            found = False
            for exclude in excludes:
                if fnmatch.fnmatch(share, exclude):
                    found = True
                    break
            if found:
                continue

            self.share_paths[share] = os.path.join(remote_drive, share)

        return '', ''

    def make_links(self, link_dir):

        """
         link_dir is the full path to the directory that will contain the links
         self.share_paths is a dict: share-name => target

         returns 3 dicts:
                new_links: a dict of all newly created links,
                all_links: a dict of all links in the link directory
                bad_links: links that do not point to the share base.

                key = link (full path)
                value = target (full path)

                for bad_link: if the value is None, the link path is not a link
         a dict of created links:
        """

        result = []
        for share, path in self.share_paths.items():

            # Create a symlink to the link directory.

            link = os.path.join(link_dir, share)

            self.all_links[link] = path

            # If it's already a link, it should point to the proper place
            # If the link name exists, but it's not a link
            # it's an error (or at least an issue).
            if os.path.exists(link):
                if os.path.islink(link):
                    relative_target = os.readlink(link)
                    target = os.path.realpath(relative_target)
                    if target != path:
                        self.bad_links[link] = target
                else:
                    self.bad_links[link] = None
                continue

            proc = subprocess.Popen(["mklink", "/D", link, path],
                                    stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                    shell=True)
            (out, err) = proc.communicate()
            #TODO: check the output. err should be empty. out should not be.
            print("program output: ", out)
            print("program err: ", err)

            self.new_links[link] = path

            result.append((out, err))

        return

    def remove_obsolete(self):

        # for each link in the directory, see if the name is a share. If not, remove it.
        #TODO: code it.
        pass
    def remove_link(self, link):

        if os.path.islink(link):
            # This removes the link, not the target
            proc = subprocess.Popen(["rmdir", link], stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE, shell=True)
            (out, err) = proc.communicate()
        else:
            out = ''
            err = "{} is not a link".format(link)

        return out, err

    # send an email to server_notifications


############## TEST ############################

#############################
# define the shares that will not be linked to.
# The routine "get_shares() will add the entry '*$' to the
# exclude list.
#############################

excludes = ['trash', 'home', 'Users']


link_dir = r'C:\share_symlinks'
remote_drive = r'\\bilbao'

mgr = LinkManager(remote_drive)

mgr.get_shares(excludes)
mgr.make_links(link_dir)

testing = False
if testing:
    for link, full_share in mgr.all_links.items():

        sysout, syserr = mgr.remove_link(link)
        # both err and out should be blank

        print('rmdir out: {}'.format(sysout))
        print('rmdir err: {}'.format(syserr))

        continue

exit(0)

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .